datadog 2.4.0 → 2.44.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 +1261 -1
- data/README.md +3 -1
- data/bin/ddprofrb +4 -4
- data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +12 -24
- data/ext/datadog_profiling_native_extension/clock_id.h +11 -3
- data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +653 -212
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +5 -5
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +33 -20
- data/ext/datadog_profiling_native_extension/collectors_stack.c +409 -113
- data/ext/datadog_profiling_native_extension/collectors_stack.h +41 -5
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +1208 -623
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +33 -8
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +240 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +85 -16
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +47 -1
- data/ext/datadog_profiling_native_extension/encoded_profile.c +80 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +99 -120
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +6 -43
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -55
- data/ext/datadog_profiling_native_extension/heap_recorder.c +762 -608
- data/ext/datadog_profiling_native_extension/heap_recorder.h +67 -28
- data/ext/datadog_profiling_native_extension/http_transport.c +108 -144
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +18 -15
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -10
- data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -40
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +796 -417
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +48 -12
- data/ext/datadog_profiling_native_extension/profiling.c +93 -27
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +77 -137
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +21 -20
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +34 -10
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
- data/ext/datadog_profiling_native_extension/stack_recorder.c +458 -302
- data/ext/datadog_profiling_native_extension/stack_recorder.h +14 -3
- data/ext/datadog_profiling_native_extension/time_helpers.h +18 -11
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +48 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +36 -0
- data/ext/libdatadog_api/crashtracker.c +33 -30
- data/ext/libdatadog_api/crashtracker.h +5 -0
- data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +85 -16
- data/ext/libdatadog_api/datadog_ruby_common.h +47 -1
- data/ext/libdatadog_api/ddsketch.c +102 -0
- data/ext/libdatadog_api/di.c +218 -0
- data/ext/libdatadog_api/extconf.rb +44 -45
- data/ext/libdatadog_api/feature_flags.c +588 -0
- data/ext/libdatadog_api/feature_flags.h +5 -0
- data/ext/libdatadog_api/helpers.h +27 -0
- data/ext/libdatadog_api/init.c +35 -0
- data/ext/libdatadog_api/library_config.c +173 -0
- data/ext/libdatadog_api/library_config.h +25 -0
- data/ext/libdatadog_api/otel_thread_context.c +268 -0
- data/ext/libdatadog_api/otel_thread_context.h +5 -0
- data/ext/libdatadog_api/process_discovery.c +118 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_api/trace_exporter.c +1932 -0
- data/ext/libdatadog_api/trace_exporter.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +116 -18
- data/lib/datadog/ai_guard/autoload.rb +10 -0
- data/lib/datadog/ai_guard/component.rb +53 -0
- data/lib/datadog/ai_guard/configuration/ext.rb +19 -0
- data/lib/datadog/ai_guard/configuration.rb +128 -0
- data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
- data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
- data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
- data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
- data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +73 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +31 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +135 -0
- data/lib/datadog/ai_guard/evaluation/client.rb +50 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +48 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +43 -0
- data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +30 -0
- data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +38 -0
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +31 -0
- data/lib/datadog/ai_guard/evaluation.rb +130 -0
- data/lib/datadog/ai_guard/ext.rb +32 -0
- data/lib/datadog/ai_guard/http_client.rb +86 -0
- data/lib/datadog/ai_guard/metrics/telemetry.rb +43 -0
- data/lib/datadog/ai_guard/redaction/replacements.rb +97 -0
- data/lib/datadog/ai_guard/redaction/result.rb +29 -0
- data/lib/datadog/ai_guard/redaction.rb +80 -0
- data/lib/datadog/ai_guard.rb +182 -0
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +68 -0
- data/lib/datadog/appsec/actions_handler.rb +49 -0
- data/lib/datadog/appsec/anonymizer.rb +16 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +104 -0
- data/lib/datadog/appsec/api_security/sampler.rb +62 -0
- data/lib/datadog/appsec/api_security.rb +23 -0
- data/lib/datadog/appsec/assets/blocked.html +1 -99
- data/lib/datadog/appsec/assets/blocked.json +1 -1
- data/lib/datadog/appsec/assets/blocked.text +3 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +44 -5
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +954 -229
- data/lib/datadog/appsec/assets/waf_rules/strict.json +109 -106
- data/lib/datadog/appsec/assets.rb +8 -8
- data/lib/datadog/appsec/autoload.rb +5 -5
- data/lib/datadog/appsec/component.rb +56 -75
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration.rb +436 -1
- data/lib/datadog/appsec/context.rb +135 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +94 -0
- data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +104 -0
- data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
- data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
- data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +146 -0
- data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
- data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
- data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +5 -6
- data/lib/datadog/appsec/contrib/devise/patcher.rb +34 -26
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +104 -0
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +70 -0
- data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +121 -0
- data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/excon/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +181 -0
- data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
- data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +166 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +4 -10
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +76 -26
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +21 -36
- data/lib/datadog/appsec/contrib/graphql/integration.rb +10 -9
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +3 -6
- data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
- data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +56 -21
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +4 -4
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +101 -106
- data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
- data/lib/datadog/appsec/contrib/rack/integration.rb +7 -7
- data/lib/datadog/appsec/contrib/rack/patcher.rb +3 -6
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +17 -15
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +118 -114
- data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
- data/lib/datadog/appsec/contrib/rails/gateway/request.rb +43 -4
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +58 -35
- data/lib/datadog/appsec/contrib/rails/integration.rb +6 -6
- data/lib/datadog/appsec/contrib/rails/patcher.rb +82 -69
- data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +29 -0
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
- data/lib/datadog/appsec/contrib/rails/request.rb +3 -3
- data/lib/datadog/appsec/contrib/rails/request_middleware.rb +2 -1
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +193 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/route_params.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +83 -71
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +6 -6
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +25 -61
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
- data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +2 -1
- data/lib/datadog/appsec/counter_sampler.rb +25 -0
- data/lib/datadog/appsec/default_header_tags.rb +52 -0
- data/lib/datadog/appsec/event.rb +80 -128
- data/lib/datadog/appsec/ext.rb +17 -1
- data/lib/datadog/appsec/extensions.rb +2 -2
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +23 -2
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +23 -0
- data/lib/datadog/appsec/instrumentation/gateway.rb +6 -24
- data/lib/datadog/appsec/metrics/collector.rb +80 -0
- data/lib/datadog/appsec/metrics/exporter.rb +48 -0
- data/lib/datadog/appsec/metrics/telemetry.rb +40 -0
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +47 -0
- data/lib/datadog/appsec/metrics.rb +14 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +60 -36
- data/lib/datadog/appsec/monitor.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +54 -60
- data/lib/datadog/appsec/rate_limiter.rb +1 -1
- data/lib/datadog/appsec/remote.rb +59 -70
- data/lib/datadog/appsec/response.rb +42 -94
- data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
- data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
- data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
- data/lib/datadog/appsec/route_normalizer.rb +80 -0
- data/lib/datadog/appsec/security_engine/engine.rb +197 -0
- data/lib/datadog/appsec/security_engine/result.rb +103 -0
- data/lib/datadog/appsec/security_engine/runner.rb +111 -0
- data/lib/datadog/appsec/security_engine.rb +9 -0
- data/lib/datadog/appsec/security_event.rb +37 -0
- data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
- data/lib/datadog/appsec/trace_keeper.rb +36 -0
- data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
- data/lib/datadog/appsec/utils/http/body.rb +41 -0
- data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
- data/lib/datadog/appsec/utils/http/media_range.rb +17 -16
- data/lib/datadog/appsec/utils/http/media_type.rb +33 -27
- data/lib/datadog/appsec/utils/http/url_encoded.rb +107 -0
- data/lib/datadog/appsec.rb +35 -28
- data/lib/datadog/auto_instrument.rb +5 -2
- data/lib/datadog/auto_instrument_base.rb +2 -1
- data/lib/datadog/core/buffer/cruby.rb +1 -1
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/buffer/thread_safe.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +46 -59
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/base.rb +19 -7
- data/lib/datadog/core/configuration/components.rb +283 -54
- data/lib/datadog/core/configuration/components_state.rb +28 -0
- data/lib/datadog/core/configuration/config_helper.rb +109 -0
- data/lib/datadog/core/configuration/deprecations.rb +36 -0
- data/lib/datadog/core/configuration/ext.rb +15 -12
- data/lib/datadog/core/configuration/option.rb +150 -84
- data/lib/datadog/core/configuration/option_definition.rb +51 -30
- data/lib/datadog/core/configuration/options.rb +58 -19
- data/lib/datadog/core/configuration/settings.rb +341 -140
- data/lib/datadog/core/configuration/stable_config.rb +32 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +426 -0
- data/lib/datadog/core/configuration.rb +51 -21
- data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
- data/lib/datadog/core/contrib/rails/utils.rb +28 -0
- data/lib/datadog/core/crashtracking/component.rb +89 -39
- data/lib/datadog/core/crashtracking/tag_builder.rb +11 -23
- data/lib/datadog/core/ddsketch.rb +19 -0
- data/lib/datadog/core/deprecations.rb +3 -3
- data/lib/datadog/core/diagnostics/environment_logger.rb +46 -9
- data/lib/datadog/core/diagnostics/health.rb +2 -2
- data/lib/datadog/core/encoding.rb +21 -5
- data/lib/datadog/core/environment/agent_info.rb +142 -0
- data/lib/datadog/core/environment/cgroup.rb +53 -28
- data/lib/datadog/core/environment/container.rb +143 -51
- data/lib/datadog/core/environment/execution.rb +3 -3
- data/lib/datadog/core/environment/ext.rb +32 -21
- data/lib/datadog/core/environment/gc.rb +1 -1
- data/lib/datadog/core/environment/git.rb +5 -4
- data/lib/datadog/core/environment/identity.rb +50 -14
- data/lib/datadog/core/environment/platform.rb +8 -8
- data/lib/datadog/core/environment/process.rb +122 -0
- data/lib/datadog/core/environment/socket.rb +15 -2
- data/lib/datadog/core/environment/variable_helpers.rb +4 -4
- data/lib/datadog/core/environment/vm_cache.rb +1 -1
- data/lib/datadog/core/environment/yjit.rb +8 -2
- data/lib/datadog/core/error.rb +15 -13
- data/lib/datadog/core/evp.rb +11 -0
- data/lib/datadog/core/extensions.rb +1 -1
- data/lib/datadog/core/feature_flags.rb +61 -0
- data/lib/datadog/core/git/ext.rb +4 -4
- data/lib/datadog/core/knuth_sampler.rb +59 -0
- data/lib/datadog/core/logger.rb +5 -5
- data/lib/datadog/core/logging/ext.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +49 -49
- data/lib/datadog/core/metrics/ext.rb +5 -5
- data/lib/datadog/core/metrics/helpers.rb +1 -1
- data/lib/datadog/core/metrics/logging.rb +8 -8
- data/lib/datadog/core/metrics/options.rb +5 -5
- data/lib/datadog/core/pin.rb +9 -9
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
- data/lib/datadog/core/process_discovery.rb +62 -0
- data/lib/datadog/core/rate_limiter.rb +16 -4
- data/lib/datadog/core/remote/client/capabilities.rb +82 -11
- data/lib/datadog/core/remote/client.rb +130 -107
- data/lib/datadog/core/remote/component.rb +97 -55
- data/lib/datadog/core/remote/configuration/content.rb +17 -4
- data/lib/datadog/core/remote/configuration/digest.rb +22 -15
- data/lib/datadog/core/remote/configuration/path.rb +9 -9
- data/lib/datadog/core/remote/configuration/repository.rb +19 -6
- data/lib/datadog/core/remote/configuration/target.rb +15 -8
- data/lib/datadog/core/remote/configuration.rb +4 -4
- data/lib/datadog/core/remote/ext.rb +3 -3
- data/lib/datadog/core/remote/negotiation.rb +10 -10
- data/lib/datadog/core/remote/tie/tracing.rb +7 -7
- data/lib/datadog/core/remote/transport/config.rb +11 -37
- data/lib/datadog/core/remote/transport/http/config.rb +39 -107
- data/lib/datadog/core/remote/transport/http/negotiation.rb +19 -92
- data/lib/datadog/core/remote/transport/http.rb +33 -106
- data/lib/datadog/core/remote/transport/negotiation.rb +9 -21
- data/lib/datadog/core/remote/worker.rb +40 -41
- data/lib/datadog/core/runtime/ext.rb +22 -22
- data/lib/datadog/core/runtime/metrics.rb +34 -14
- data/lib/datadog/core/semaphore.rb +32 -0
- data/lib/datadog/core/tag_builder.rb +52 -0
- data/lib/datadog/core/tag_normalizer.rb +84 -0
- data/lib/datadog/core/telemetry/component.rb +143 -60
- data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
- data/lib/datadog/core/telemetry/emitter.rb +26 -14
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +67 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
- data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -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 +274 -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 +66 -0
- data/lib/datadog/core/telemetry/event.rb +21 -392
- data/lib/datadog/core/telemetry/ext.rb +11 -9
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/logger.rb +6 -3
- data/lib/datadog/core/telemetry/logging.rb +35 -17
- data/lib/datadog/core/telemetry/metric.rb +37 -15
- data/lib/datadog/core/telemetry/metrics_collection.rb +2 -2
- data/lib/datadog/core/telemetry/metrics_manager.rb +10 -1
- data/lib/datadog/core/telemetry/request.rb +23 -11
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +66 -0
- data/lib/datadog/core/telemetry/transport/http.rb +68 -0
- data/lib/datadog/core/telemetry/transport/telemetry.rb +42 -0
- data/lib/datadog/core/telemetry/worker.rb +214 -35
- data/lib/datadog/core/transport/ext.rb +14 -10
- data/lib/datadog/core/transport/http/adapters/net.rb +19 -4
- data/lib/datadog/core/transport/http/adapters/test.rb +3 -2
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +5 -5
- data/lib/datadog/core/transport/http/api/endpoint.rb +10 -5
- data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +5 -5
- data/lib/datadog/core/transport/http/api/map.rb +1 -1
- data/lib/datadog/{tracing → core}/transport/http/builder.rb +62 -36
- data/lib/datadog/core/transport/http/client.rb +80 -0
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/transport/http/response.rb +5 -1
- data/lib/datadog/core/transport/http.rb +80 -0
- data/lib/datadog/core/transport/parcel.rb +61 -9
- data/lib/datadog/core/transport/response.rb +19 -1
- data/lib/datadog/core/transport/transport.rb +90 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +181 -29
- data/lib/datadog/core/utils/base64_codec.rb +23 -0
- data/lib/datadog/core/utils/duration.rb +33 -33
- data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
- data/lib/datadog/core/utils/fnv.rb +26 -0
- data/lib/datadog/core/utils/forking.rb +5 -3
- data/lib/datadog/core/utils/hash.rb +0 -23
- data/lib/datadog/core/utils/lru_cache.rb +45 -0
- data/lib/datadog/core/utils/network.rb +34 -13
- data/lib/datadog/core/utils/only_once.rb +1 -1
- data/lib/datadog/core/utils/only_once_successful.rb +25 -8
- data/lib/datadog/core/utils/safe_dup.rb +4 -3
- data/lib/datadog/core/utils/sequence.rb +3 -4
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
- data/lib/datadog/core/utils/time.rb +19 -33
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/utils/url.rb +1 -1
- data/lib/datadog/core/utils.rb +14 -5
- 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 +41 -15
- data/lib/datadog/core/workers/interval_loop.rb +63 -4
- data/lib/datadog/core/workers/polling.rb +4 -2
- data/lib/datadog/core/workers/queue.rb +96 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +14 -6
- data/lib/datadog/core.rb +20 -3
- data/lib/datadog/data_streams/configuration.rb +50 -0
- data/lib/datadog/data_streams/ext.rb +11 -0
- data/lib/datadog/data_streams/extensions.rb +16 -0
- data/lib/datadog/data_streams/pathway_context.rb +167 -0
- data/lib/datadog/data_streams/processor.rb +542 -0
- data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
- data/lib/datadog/data_streams/transport/http.rb +36 -0
- data/lib/datadog/data_streams/transport/stats.rb +39 -0
- data/lib/datadog/data_streams.rb +100 -0
- data/lib/datadog/di/base.rb +123 -0
- data/lib/datadog/di/boot.rb +47 -0
- data/lib/datadog/di/capture_expression.rb +21 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
- data/lib/datadog/di/capture_limits.rb +41 -0
- data/lib/datadog/di/code_tracker.rb +256 -18
- data/lib/datadog/di/component.rb +220 -0
- data/lib/datadog/di/configuration.rb +241 -2
- data/lib/datadog/di/context.rb +82 -0
- data/lib/datadog/di/contrib/active_record.rb +41 -0
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +28 -0
- data/lib/datadog/di/el/compiler.rb +244 -0
- data/lib/datadog/di/el/evaluator.rb +239 -0
- data/lib/datadog/di/el/expression.rb +53 -0
- data/lib/datadog/di/el.rb +5 -0
- data/lib/datadog/di/error.rb +66 -0
- data/lib/datadog/di/fatal_exceptions.rb +26 -0
- data/lib/datadog/di/instrumenter.rb +978 -0
- data/lib/datadog/di/logger.rb +30 -0
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +188 -14
- data/lib/datadog/di/probe_builder.rb +132 -3
- data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
- data/lib/datadog/di/probe_file_loader.rb +87 -0
- data/lib/datadog/di/probe_manager.rb +352 -0
- data/lib/datadog/di/probe_notification_builder.rb +452 -0
- data/lib/datadog/di/probe_notifier_worker.rb +381 -0
- data/lib/datadog/di/probe_repository.rb +198 -0
- data/lib/datadog/di/proc_responder.rb +36 -0
- data/lib/datadog/di/redactor.rb +24 -3
- data/lib/datadog/di/remote.rb +310 -0
- data/lib/datadog/di/serializer.rb +487 -96
- data/lib/datadog/di/transport/diagnostics.rb +32 -0
- data/lib/datadog/di/transport/http/diagnostics.rb +35 -0
- data/lib/datadog/di/transport/http/input.rb +45 -0
- data/lib/datadog/di/transport/http.rb +81 -0
- data/lib/datadog/di/transport/input.rb +144 -0
- data/lib/datadog/di/utils.rb +170 -0
- data/lib/datadog/di.rb +224 -2
- data/lib/datadog/error_tracking/collector.rb +88 -0
- data/lib/datadog/error_tracking/component.rb +167 -0
- data/lib/datadog/error_tracking/configuration.rb +64 -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 +253 -0
- data/lib/datadog/kit/appsec/events.rb +39 -26
- data/lib/datadog/kit/enable_core_dumps.rb +3 -3
- data/lib/datadog/kit/identity.rb +34 -24
- data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
- data/lib/datadog/kit.rb +1 -1
- data/lib/datadog/open_feature/agentless/configuration_source.rb +246 -0
- data/lib/datadog/open_feature/agentless/parser.rb +43 -0
- data/lib/datadog/open_feature/agentless/response.rb +19 -0
- data/lib/datadog/open_feature/agentless/transport.rb +103 -0
- data/lib/datadog/open_feature/component.rb +165 -0
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +90 -0
- data/lib/datadog/open_feature/configuration/source/resolution.rb +22 -0
- data/lib/datadog/open_feature/configuration/source.rb +43 -0
- data/lib/datadog/open_feature/configuration.rb +168 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +96 -0
- data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
- data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
- data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
- data/lib/datadog/open_feature/exposures/event.rb +67 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
- data/lib/datadog/open_feature/exposures/worker.rb +116 -0
- data/lib/datadog/open_feature/ext.rb +40 -0
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +442 -0
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +544 -0
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +105 -0
- data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +51 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook/codec.rb +58 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook/span_enrichment_state.rb +96 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook/span_enrichment_state_store.rb +49 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +184 -0
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
- data/lib/datadog/open_feature/native_evaluator.rb +74 -0
- data/lib/datadog/open_feature/noop_evaluator.rb +31 -0
- data/lib/datadog/open_feature/provider.rb +235 -0
- data/lib/datadog/open_feature/remote.rb +67 -0
- data/lib/datadog/open_feature/resolution_details.rb +37 -0
- data/lib/datadog/open_feature/transport.rb +126 -0
- data/lib/datadog/open_feature.rb +19 -0
- data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
- data/lib/datadog/opentelemetry/api/context.rb +25 -10
- data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
- data/lib/datadog/opentelemetry/ext.rb +9 -0
- data/lib/datadog/opentelemetry/logs.rb +98 -0
- data/lib/datadog/opentelemetry/metrics.rb +90 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +69 -5
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
- data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +21 -15
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +24 -21
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +43 -39
- data/lib/datadog/opentelemetry/sdk.rb +19 -0
- data/lib/datadog/opentelemetry/signal_configuration.rb +57 -0
- data/lib/datadog/opentelemetry/trace.rb +8 -5
- data/lib/datadog/opentelemetry.rb +11 -6
- data/lib/datadog/profiling/collectors/code_provenance.rb +84 -16
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +60 -3
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -4
- data/lib/datadog/profiling/collectors/info.rb +62 -8
- data/lib/datadog/profiling/collectors/thread_context.rb +25 -18
- data/lib/datadog/profiling/component.rb +123 -104
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +51 -17
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
- data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
- data/lib/datadog/profiling/ext.rb +2 -17
- data/lib/datadog/profiling/flush.rb +26 -17
- data/lib/datadog/profiling/http_transport.rb +30 -96
- data/lib/datadog/profiling/load_native_extension.rb +3 -35
- data/lib/datadog/profiling/profiler.rb +31 -12
- data/lib/datadog/profiling/scheduler.rb +19 -10
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +38 -18
- data/lib/datadog/profiling/tag_builder.rb +41 -41
- data/lib/datadog/profiling/tasks/exec.rb +11 -6
- data/lib/datadog/profiling/tasks/help.rb +1 -0
- data/lib/datadog/profiling/tasks/setup.rb +4 -2
- data/lib/datadog/profiling.rb +42 -37
- data/lib/datadog/ruby_version.rb +25 -0
- data/lib/datadog/single_step_instrument.rb +11 -2
- data/lib/datadog/symbol_database/component.rb +734 -0
- data/lib/datadog/symbol_database/configuration.rb +73 -0
- data/lib/datadog/symbol_database/extensions.rb +19 -0
- data/lib/datadog/symbol_database/extractor.rb +1092 -0
- data/lib/datadog/symbol_database/file_hash.rb +48 -0
- data/lib/datadog/symbol_database/logger.rb +43 -0
- data/lib/datadog/symbol_database/remote.rb +195 -0
- data/lib/datadog/symbol_database/scope.rb +102 -0
- data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
- data/lib/datadog/symbol_database/service_version.rb +66 -0
- data/lib/datadog/symbol_database/symbol.rb +69 -0
- data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
- data/lib/datadog/symbol_database/transport/http.rb +45 -0
- data/lib/datadog/symbol_database/transport.rb +54 -0
- data/lib/datadog/symbol_database/uploader.rb +230 -0
- data/lib/datadog/symbol_database.rb +71 -0
- data/lib/datadog/tracing/analytics.rb +2 -2
- data/lib/datadog/tracing/buffer.rb +15 -15
- data/lib/datadog/tracing/client_ip.rb +4 -4
- data/lib/datadog/tracing/component.rb +63 -23
- data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +16 -16
- data/lib/datadog/tracing/configuration/ext.rb +62 -33
- data/lib/datadog/tracing/configuration/http.rb +2 -2
- data/lib/datadog/tracing/configuration/settings.rb +182 -34
- data/lib/datadog/tracing/context.rb +27 -5
- data/lib/datadog/tracing/context_provider.rb +12 -8
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_cable/event.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +9 -6
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +8 -5
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +9 -6
- data/lib/datadog/tracing/contrib/action_cable/events.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -5
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +10 -7
- 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 +7 -4
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +8 -8
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +4 -4
- data/lib/datadog/tracing/contrib/action_mailer/events.rb +3 -3
- data/lib/datadog/tracing/contrib/action_mailer/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +11 -7
- data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +38 -20
- data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +48 -13
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +5 -3
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +10 -8
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +10 -7
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +2 -3
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/action_view/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +10 -7
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +12 -9
- data/lib/datadog/tracing/contrib/action_view/events.rb +3 -3
- data/lib/datadog/tracing/contrib/action_view/ext.rb +10 -10
- data/lib/datadog/tracing/contrib/action_view/integration.rb +14 -11
- data/lib/datadog/tracing/contrib/action_view/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/action_view/utils.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/data_streams.rb +62 -0
- data/lib/datadog/tracing/contrib/active_job/event.rb +11 -11
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +11 -8
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +11 -8
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +11 -8
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +11 -8
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +11 -8
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +11 -8
- data/lib/datadog/tracing/contrib/active_job/events.rb +6 -6
- data/lib/datadog/tracing/contrib/active_job/ext.rb +23 -23
- data/lib/datadog/tracing/contrib/active_job/integration.rb +10 -7
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +21 -5
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +4 -4
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +8 -8
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +9 -10
- data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +3 -3
- data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +10 -10
- data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +5 -6
- data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/active_record/configuration/makara_resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +9 -9
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/active_record/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +10 -10
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +17 -19
- data/lib/datadog/tracing/contrib/active_record/events.rb +3 -3
- data/lib/datadog/tracing/contrib/active_record/ext.rb +15 -15
- data/lib/datadog/tracing/contrib/active_record/integration.rb +16 -12
- data/lib/datadog/tracing/contrib/active_record/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/utils.rb +19 -19
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +29 -21
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +40 -8
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +8 -4
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +16 -6
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +26 -3
- data/lib/datadog/tracing/contrib/active_support/ext.rb +16 -16
- data/lib/datadog/tracing/contrib/active_support/integration.rb +11 -8
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +3 -2
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +9 -11
- 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 +5 -5
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/ext.rb +27 -27
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +21 -13
- data/lib/datadog/tracing/contrib/aws/integration.rb +11 -8
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +9 -3
- data/lib/datadog/tracing/contrib/aws/patcher.rb +10 -6
- data/lib/datadog/tracing/contrib/aws/service/base.rb +2 -1
- data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +4 -4
- data/lib/datadog/tracing/contrib/aws/service/s3.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/service/sns.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/service/sqs.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/service/states.rb +5 -5
- data/lib/datadog/tracing/contrib/aws/services.rb +14 -14
- data/lib/datadog/tracing/contrib/component.rb +3 -3
- data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +8 -5
- data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +2 -2
- data/lib/datadog/tracing/contrib/configurable.rb +24 -9
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
- data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +5 -5
- data/lib/datadog/tracing/contrib/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/dalli/ext.rb +16 -15
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +6 -10
- data/lib/datadog/tracing/contrib/dalli/integration.rb +10 -7
- data/lib/datadog/tracing/contrib/dalli/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +3 -3
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +14 -14
- data/lib/datadog/tracing/contrib/delayed_job/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +7 -5
- data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +6 -2
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +18 -17
- data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +8 -8
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +63 -64
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +9 -9
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +7 -3
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +19 -17
- data/lib/datadog/tracing/contrib/ethon/ext.rb +16 -14
- data/lib/datadog/tracing/contrib/ethon/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +4 -11
- data/lib/datadog/tracing/contrib/ethon/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +21 -10
- data/lib/datadog/tracing/contrib/excon/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/excon/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/excon/middleware.rb +18 -17
- data/lib/datadog/tracing/contrib/excon/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/ext.rb +23 -20
- data/lib/datadog/tracing/contrib/extensions.rb +57 -14
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +20 -13
- data/lib/datadog/tracing/contrib/faraday/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/faraday/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +20 -17
- data/lib/datadog/tracing/contrib/faraday/patcher.rb +6 -6
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +11 -7
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +69 -36
- data/lib/datadog/tracing/contrib/grape/ext.rb +15 -15
- data/lib/datadog/tracing/contrib/grape/instrumentation.rb +15 -10
- data/lib/datadog/tracing/contrib/grape/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/grape/patcher.rb +10 -5
- data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +20 -2
- data/lib/datadog/tracing/contrib/graphql/ext.rb +11 -5
- data/lib/datadog/tracing/contrib/graphql/integration.rb +9 -9
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -8
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +174 -41
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +7 -4
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +26 -24
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +14 -18
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +6 -6
- data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +13 -8
- data/lib/datadog/tracing/contrib/grpc/ext.rb +14 -13
- data/lib/datadog/tracing/contrib/grpc/formatting.rb +7 -7
- data/lib/datadog/tracing/contrib/grpc/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/grpc/intercept_with_datadog.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc.rb +7 -6
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +4 -3
- data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/hanami/ext.rb +8 -8
- data/lib/datadog/tracing/contrib/hanami/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/hanami/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +5 -4
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +14 -14
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +1 -7
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +20 -9
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +6 -6
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +13 -8
- data/lib/datadog/tracing/contrib/http/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +20 -24
- data/lib/datadog/tracing/contrib/http/integration.rb +9 -8
- data/lib/datadog/tracing/contrib/http/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/http.rb +7 -6
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +20 -9
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +21 -27
- data/lib/datadog/tracing/contrib/httpclient/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +20 -9
- data/lib/datadog/tracing/contrib/httprb/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +21 -29
- data/lib/datadog/tracing/contrib/httprb/integration.rb +9 -6
- 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 +5 -4
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +8 -4
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +6 -6
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +6 -6
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +6 -6
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +6 -6
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +11 -6
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +11 -6
- data/lib/datadog/tracing/contrib/kafka/events.rb +10 -10
- data/lib/datadog/tracing/contrib/kafka/ext.rb +40 -40
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +8 -5
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +17 -3
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +31 -0
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +50 -0
- data/lib/datadog/tracing/contrib/karafka/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
- data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +77 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +102 -0
- data/lib/datadog/tracing/contrib/karafka.rb +38 -0
- data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/lograge/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +13 -11
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +19 -18
- data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +9 -6
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +10 -10
- data/lib/datadog/tracing/contrib/mongodb/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +38 -24
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +9 -3
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +25 -18
- data/lib/datadog/tracing/contrib/mysql2/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/mysql2/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +19 -2
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +31 -21
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +8 -6
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +75 -77
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +10 -10
- data/lib/datadog/tracing/contrib/patchable.rb +1 -1
- data/lib/datadog/tracing/contrib/patcher.rb +15 -14
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +9 -3
- data/lib/datadog/tracing/contrib/pg/ext.rb +19 -19
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +21 -24
- data/lib/datadog/tracing/contrib/pg/integration.rb +5 -5
- 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/ext.rb +22 -22
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +11 -13
- data/lib/datadog/tracing/contrib/presto/integration.rb +8 -5
- data/lib/datadog/tracing/contrib/presto/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +2 -2
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +26 -13
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +7 -3
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +29 -5
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +7 -4
- data/lib/datadog/tracing/contrib/que/ext.rb +19 -18
- data/lib/datadog/tracing/contrib/que/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/que/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +3 -2
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/event.rb +6 -10
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +5 -5
- data/lib/datadog/tracing/contrib/racecar/events/consume.rb +4 -4
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +5 -5
- data/lib/datadog/tracing/contrib/racecar/events.rb +4 -4
- data/lib/datadog/tracing/contrib/racecar/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/racecar/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/racecar/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +14 -4
- data/lib/datadog/tracing/contrib/rack/ext.rb +43 -15
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +13 -3
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +55 -32
- data/lib/datadog/tracing/contrib/rack/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +102 -63
- data/lib/datadog/tracing/contrib/rack/patcher.rb +6 -6
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +8 -7
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +131 -7
- data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/rails/ext.rb +16 -14
- data/lib/datadog/tracing/contrib/rails/framework.rb +12 -12
- data/lib/datadog/tracing/contrib/rails/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +4 -4
- data/lib/datadog/tracing/contrib/rails/patcher.rb +11 -9
- data/lib/datadog/tracing/contrib/rails/railtie.rb +4 -4
- data/lib/datadog/tracing/contrib/rails/runner.rb +64 -40
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/rake/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +13 -11
- data/lib/datadog/tracing/contrib/rake/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/rake/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +5 -5
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/ext.rb +19 -18
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/redis/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/redis/patcher.rb +12 -12
- data/lib/datadog/tracing/contrib/redis/quantize.rb +41 -7
- data/lib/datadog/tracing/contrib/redis/tags.rb +7 -12
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +20 -12
- data/lib/datadog/tracing/contrib/registerable.rb +11 -0
- data/lib/datadog/tracing/contrib/registry.rb +1 -1
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/resque/ext.rb +7 -7
- data/lib/datadog/tracing/contrib/resque/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/resque/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/resque/resque_job.rb +7 -6
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +7 -4
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +13 -11
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +8 -5
- data/lib/datadog/tracing/contrib/rest_client/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +19 -15
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/roda/ext.rb +6 -5
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +12 -7
- data/lib/datadog/tracing/contrib/roda/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/roda/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +5 -5
- 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 +8 -11
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +7 -6
- data/lib/datadog/tracing/contrib/sequel/ext.rb +12 -8
- data/lib/datadog/tracing/contrib/sequel/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
- data/lib/datadog/tracing/contrib/sequel/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/sequel/utils.rb +103 -16
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/shoryuken/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/shoryuken/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +3 -2
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +15 -9
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +7 -3
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +14 -9
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +31 -29
- data/lib/datadog/tracing/contrib/sidekiq/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +8 -8
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +19 -15
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +10 -10
- data/lib/datadog/tracing/contrib/sidekiq.rb +7 -6
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +8 -4
- data/lib/datadog/tracing/contrib/sinatra/env.rb +6 -6
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +17 -16
- data/lib/datadog/tracing/contrib/sinatra/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/sinatra/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +11 -10
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +46 -45
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/sneakers/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/sneakers/integration.rb +19 -8
- data/lib/datadog/tracing/contrib/sneakers/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +5 -4
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +9 -4
- data/lib/datadog/tracing/contrib/status_range_env_parser.rb +2 -2
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/stripe/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/stripe/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/stripe/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/stripe/request.rb +5 -5
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sucker_punch/exception_handler.rb +1 -1
- data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +13 -13
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +5 -4
- data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +9 -3
- data/lib/datadog/tracing/contrib/trilogy/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +10 -12
- data/lib/datadog/tracing/contrib/trilogy/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/trilogy/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/utils/database.rb +5 -5
- data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +17 -15
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +16 -16
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
- data/lib/datadog/tracing/contrib.rb +62 -52
- data/lib/datadog/tracing/correlation.rb +21 -14
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +23 -15
- data/lib/datadog/tracing/diagnostics/ext.rb +19 -19
- data/lib/datadog/tracing/diagnostics/health.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +9 -9
- data/lib/datadog/tracing/distributed/b3_single.rb +6 -6
- data/lib/datadog/tracing/distributed/baggage.rb +250 -0
- data/lib/datadog/tracing/distributed/datadog.rb +41 -38
- data/lib/datadog/tracing/distributed/fetcher.rb +1 -1
- data/lib/datadog/tracing/distributed/helpers.rb +4 -4
- data/lib/datadog/tracing/distributed/none.rb +4 -2
- data/lib/datadog/tracing/distributed/propagation.rb +73 -14
- data/lib/datadog/tracing/distributed/propagation_policy.rb +47 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +31 -259
- data/lib/datadog/tracing/distributed/trace_state/datadog.rb +233 -0
- data/lib/datadog/tracing/distributed/trace_state/ext.rb +44 -0
- data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +156 -0
- data/lib/datadog/tracing/distributed/trace_state.rb +121 -0
- data/lib/datadog/tracing/event.rb +6 -8
- data/lib/datadog/tracing/ext.rb +9 -0
- data/lib/datadog/tracing/flush.rb +1 -1
- data/lib/datadog/tracing/metadata/analytics.rb +3 -3
- data/lib/datadog/tracing/metadata/errors.rb +8 -8
- data/lib/datadog/tracing/metadata/ext.rb +89 -59
- data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
- data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
- data/lib/datadog/tracing/metadata/tagging.rb +9 -9
- data/lib/datadog/tracing/metadata.rb +5 -3
- data/lib/datadog/tracing/otel_thread_context.rb +99 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +5 -3
- data/lib/datadog/tracing/pipeline/span_processor.rb +3 -1
- data/lib/datadog/tracing/pipeline.rb +4 -4
- data/lib/datadog/tracing/remote.rb +228 -30
- data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/ext.rb +9 -9
- data/lib/datadog/tracing/sampling/matcher.rb +4 -4
- data/lib/datadog/tracing/sampling/priority_sampler.rb +20 -5
- data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +3 -3
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/rate_sampler.rb +9 -19
- data/lib/datadog/tracing/sampling/rule.rb +5 -5
- data/lib/datadog/tracing/sampling/rule_sampler.rb +91 -58
- data/lib/datadog/tracing/sampling/sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/span/ext.rb +3 -3
- data/lib/datadog/tracing/sampling/span/matcher.rb +2 -2
- data/lib/datadog/tracing/sampling/span/rule.rb +1 -2
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +11 -11
- data/lib/datadog/tracing/sampling/span/sampler.rb +0 -7
- data/lib/datadog/tracing/span.rb +29 -12
- data/lib/datadog/tracing/span_event.rb +125 -5
- data/lib/datadog/tracing/span_link.rb +12 -12
- data/lib/datadog/tracing/span_operation.rb +120 -40
- data/lib/datadog/tracing/sync_writer.rb +22 -14
- data/lib/datadog/tracing/trace_digest.rb +58 -28
- data/lib/datadog/tracing/trace_operation.rb +263 -120
- data/lib/datadog/tracing/trace_segment.rb +18 -16
- data/lib/datadog/tracing/tracer.rb +208 -73
- data/lib/datadog/tracing/transport/http/client.rb +17 -30
- data/lib/datadog/tracing/transport/http/statistics.rb +2 -2
- data/lib/datadog/tracing/transport/http/traces.rb +11 -90
- data/lib/datadog/tracing/transport/http.rb +26 -73
- data/lib/datadog/tracing/transport/io/client.rb +13 -16
- data/lib/datadog/tracing/transport/io/response.rb +1 -1
- data/lib/datadog/tracing/transport/io/traces.rb +33 -39
- data/lib/datadog/tracing/transport/io.rb +3 -3
- data/lib/datadog/tracing/transport/native/response.rb +71 -0
- data/lib/datadog/tracing/transport/native.rb +379 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +47 -23
- data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
- data/lib/datadog/tracing/transport/statistics.rb +3 -3
- data/lib/datadog/tracing/transport/trace_formatter.rb +49 -10
- data/lib/datadog/tracing/transport/traces.rb +45 -99
- data/lib/datadog/tracing/utils.rb +3 -3
- data/lib/datadog/tracing/workers.rb +12 -10
- data/lib/datadog/tracing/writer.rb +54 -39
- data/lib/datadog/tracing.rb +19 -6
- data/lib/datadog/version.rb +4 -4
- data/lib/datadog.rb +21 -5
- metadata +372 -70
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
- data/ext/datadog_profiling_loader/extconf.rb +0 -60
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
- data/ext/libdatadog_api/macos_development.md +0 -26
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
- data/lib/datadog/appsec/configuration/settings.rb +0 -207
- data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
- data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
- data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -59
- data/lib/datadog/appsec/contrib/patcher.rb +0 -12
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -81
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -60
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -66
- data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -66
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -61
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -58
- data/lib/datadog/appsec/processor/actions.rb +0 -49
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
- data/lib/datadog/appsec/processor.rb +0 -170
- data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
- data/lib/datadog/appsec/reactive/engine.rb +0 -47
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
- data/lib/datadog/appsec/scope.rb +0 -61
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
- data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
- data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
- data/lib/datadog/core/remote/transport/http/api.rb +0 -58
- data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
- data/lib/datadog/core/remote/transport/http/client.rb +0 -48
- data/lib/datadog/core/telemetry/http/env.rb +0 -20
- data/lib/datadog/core/telemetry/http/ext.rb +0 -28
- data/lib/datadog/core/telemetry/http/response.rb +0 -70
- data/lib/datadog/core/telemetry/http/transport.rb +0 -90
- data/lib/datadog/core/utils/base64.rb +0 -22
- data/lib/datadog/di/configuration/settings.rb +0 -163
- data/lib/datadog/tracing/contrib/rails/utils.rb +0 -26
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -84
- data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
- data/lib/datadog/tracing/transport/http/api.rb +0 -43
- data/lib/datadog/tracing/workers/trace_writer.rb +0 -196
|
@@ -0,0 +1,1932 @@
|
|
|
1
|
+
#include <ruby.h>
|
|
2
|
+
#ifdef __GNUC__
|
|
3
|
+
#pragma GCC diagnostic push
|
|
4
|
+
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
5
|
+
#endif
|
|
6
|
+
#include <ruby/encoding.h>
|
|
7
|
+
#ifdef __GNUC__
|
|
8
|
+
#pragma GCC diagnostic pop
|
|
9
|
+
#endif
|
|
10
|
+
#include <ruby/thread.h>
|
|
11
|
+
#include <limits.h>
|
|
12
|
+
#include <stdbool.h>
|
|
13
|
+
#include <string.h>
|
|
14
|
+
#include <datadog/data-pipeline.h>
|
|
15
|
+
#include <datadog/shared-runtime.h>
|
|
16
|
+
|
|
17
|
+
#include "datadog_ruby_common.h"
|
|
18
|
+
#include "helpers.h"
|
|
19
|
+
#include "trace_exporter.h"
|
|
20
|
+
|
|
21
|
+
/* ========================================================================
|
|
22
|
+
* Forward declarations
|
|
23
|
+
* ======================================================================== */
|
|
24
|
+
|
|
25
|
+
typedef struct {
|
|
26
|
+
ddog_TracerSpan *span;
|
|
27
|
+
} raw_span_owner;
|
|
28
|
+
|
|
29
|
+
/* Internal: convert a Ruby Span into the supplied raw Rust span owner */
|
|
30
|
+
static void convert_ruby_span_to_rust(VALUE span, VALUE native_events_supported, raw_span_owner *owner);
|
|
31
|
+
|
|
32
|
+
/* TracerSpan methods */
|
|
33
|
+
static VALUE _native_from_span(VALUE klass, VALUE span);
|
|
34
|
+
|
|
35
|
+
/* TraceExporter methods */
|
|
36
|
+
static VALUE _native_exporter_new(int argc, VALUE *argv, VALUE klass);
|
|
37
|
+
static VALUE _native_send_traces(VALUE self, VALUE traces, VALUE native_events_supported);
|
|
38
|
+
static VALUE _native_before_fork(VALUE self);
|
|
39
|
+
static VALUE _native_after_fork_in_parent(VALUE self);
|
|
40
|
+
static VALUE _native_after_fork_in_child(VALUE self);
|
|
41
|
+
|
|
42
|
+
/* Response helpers */
|
|
43
|
+
static VALUE create_ok_response(long trace_count, VALUE payload);
|
|
44
|
+
static VALUE create_error_response(ddog_TraceExporterErrorCode code,
|
|
45
|
+
long trace_count);
|
|
46
|
+
|
|
47
|
+
/* GC / TypedData */
|
|
48
|
+
static void tracer_span_dfree(void *ptr);
|
|
49
|
+
static void trace_exporter_dfree(void *ptr);
|
|
50
|
+
|
|
51
|
+
/* ========================================================================
|
|
52
|
+
* Cached Ruby intern IDs
|
|
53
|
+
* ======================================================================== */
|
|
54
|
+
|
|
55
|
+
/* Instance variable IDs on Datadog::Tracing::Span */
|
|
56
|
+
static ID at_name_id;
|
|
57
|
+
static ID at_service_id;
|
|
58
|
+
static ID at_resource_id;
|
|
59
|
+
static ID at_type_id;
|
|
60
|
+
static ID at_id_id;
|
|
61
|
+
static ID at_parent_id_id;
|
|
62
|
+
static ID at_trace_id_id;
|
|
63
|
+
static ID at_start_time_id;
|
|
64
|
+
static ID at_duration_id;
|
|
65
|
+
static ID at_status_id;
|
|
66
|
+
static ID at_meta_id;
|
|
67
|
+
static ID at_metrics_id;
|
|
68
|
+
static ID at_events_id;
|
|
69
|
+
static ID at_links_id;
|
|
70
|
+
static ID at_metastruct_id;
|
|
71
|
+
|
|
72
|
+
/* Method IDs for time / integer operations */
|
|
73
|
+
static ID id_duration_method;
|
|
74
|
+
static ID id_to_a;
|
|
75
|
+
static ID id_to_native_format;
|
|
76
|
+
static ID id_to_hash;
|
|
77
|
+
static ID id_to_h;
|
|
78
|
+
static ID id_negative_p;
|
|
79
|
+
|
|
80
|
+
/* SpanEvent native-format hash keys */
|
|
81
|
+
static VALUE event_name_key = Qnil;
|
|
82
|
+
static VALUE event_time_key = Qnil;
|
|
83
|
+
static VALUE event_attributes_key = Qnil;
|
|
84
|
+
static ID event_type_id;
|
|
85
|
+
static ID event_string_value_id;
|
|
86
|
+
static ID event_bool_value_id;
|
|
87
|
+
static ID event_int_value_id;
|
|
88
|
+
static ID event_double_value_id;
|
|
89
|
+
static ID event_array_value_id;
|
|
90
|
+
static ID event_values_id;
|
|
91
|
+
|
|
92
|
+
/* Canonical SpanLink#to_hash field IDs */
|
|
93
|
+
static ID link_trace_id_id;
|
|
94
|
+
static ID link_trace_id_high_id;
|
|
95
|
+
static ID link_span_id_id;
|
|
96
|
+
static ID link_attributes_id;
|
|
97
|
+
static ID link_tracestate_id;
|
|
98
|
+
static ID link_flags_id;
|
|
99
|
+
|
|
100
|
+
/* Resolved lazily because AppSec may load after this extension. */
|
|
101
|
+
static VALUE serializable_backtrace_class = Qnil;
|
|
102
|
+
|
|
103
|
+
/* Response class (loaded from Ruby) */
|
|
104
|
+
static VALUE response_class = Qnil;
|
|
105
|
+
static ID id_new;
|
|
106
|
+
|
|
107
|
+
/* Response keyword-argument IDs, cached to avoid re-interning per send */
|
|
108
|
+
static ID kw_ok;
|
|
109
|
+
static ID kw_internal_error;
|
|
110
|
+
static ID kw_server_error;
|
|
111
|
+
static ID kw_client_error;
|
|
112
|
+
static ID kw_trace_count;
|
|
113
|
+
static ID kw_payload;
|
|
114
|
+
|
|
115
|
+
/* ========================================================================
|
|
116
|
+
* Ruby class references (marked as GC roots)
|
|
117
|
+
* ======================================================================== */
|
|
118
|
+
|
|
119
|
+
static VALUE tracer_span_class = Qnil;
|
|
120
|
+
static VALUE trace_exporter_class = Qnil;
|
|
121
|
+
|
|
122
|
+
/* ========================================================================
|
|
123
|
+
* TypedData definitions
|
|
124
|
+
* ======================================================================== */
|
|
125
|
+
|
|
126
|
+
static const rb_data_type_t tracer_span_typed_data = {
|
|
127
|
+
.wrap_struct_name = "Datadog::Tracing::Transport::Native::TracerSpan",
|
|
128
|
+
.function = {
|
|
129
|
+
.dmark = NULL,
|
|
130
|
+
.dfree = tracer_span_dfree,
|
|
131
|
+
.dsize = NULL,
|
|
132
|
+
},
|
|
133
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
static void tracer_span_dfree(void *ptr) {
|
|
137
|
+
if (ptr != NULL) {
|
|
138
|
+
ddog_tracer_span_free((ddog_TracerSpan *)ptr);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* The TraceExporter wrapper owns both the Rust exporter and the SharedRuntime
|
|
144
|
+
* that drives its background workers. Fork-safety hooks operate on the
|
|
145
|
+
* runtime, while send/receive operate on the exporter.
|
|
146
|
+
*/
|
|
147
|
+
typedef struct {
|
|
148
|
+
ddog_TraceExporter *exporter;
|
|
149
|
+
const ddog_ForkSafeRuntime *runtime;
|
|
150
|
+
} trace_exporter_t;
|
|
151
|
+
|
|
152
|
+
static const rb_data_type_t trace_exporter_typed_data = {
|
|
153
|
+
.wrap_struct_name = "Datadog::Tracing::Transport::Native::TraceExporter",
|
|
154
|
+
.function = {
|
|
155
|
+
.dmark = NULL,
|
|
156
|
+
.dfree = trace_exporter_dfree,
|
|
157
|
+
.dsize = NULL,
|
|
158
|
+
},
|
|
159
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
static void trace_exporter_dfree(void *ptr) {
|
|
163
|
+
if (ptr != NULL) {
|
|
164
|
+
trace_exporter_t *wrapper = (trace_exporter_t *)ptr;
|
|
165
|
+
if (wrapper->exporter != NULL) {
|
|
166
|
+
ddog_trace_exporter_free(wrapper->exporter);
|
|
167
|
+
}
|
|
168
|
+
if (wrapper->runtime != NULL) {
|
|
169
|
+
ddog_shared_runtime_free(wrapper->runtime);
|
|
170
|
+
}
|
|
171
|
+
ruby_xfree(wrapper);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* ========================================================================
|
|
176
|
+
* Error handling
|
|
177
|
+
* ======================================================================== */
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* If +err+ is non-NULL, copies the message, frees the error struct, and
|
|
181
|
+
* raises a Ruby RuntimeError. Does not return on error.
|
|
182
|
+
*/
|
|
183
|
+
static inline void check_exporter_error(const char *context,
|
|
184
|
+
ddog_TraceExporterError *err) {
|
|
185
|
+
if (err == NULL) return;
|
|
186
|
+
|
|
187
|
+
char buf[MAX_RAISE_MESSAGE_SIZE];
|
|
188
|
+
if (err->msg != NULL) {
|
|
189
|
+
snprintf(buf, sizeof(buf), "%s: %s", context, err->msg);
|
|
190
|
+
} else {
|
|
191
|
+
snprintf(buf, sizeof(buf), "%s: (unknown error)", context);
|
|
192
|
+
}
|
|
193
|
+
ddog_trace_exporter_error_free(err);
|
|
194
|
+
raise_error(rb_eRuntimeError, "%s", buf);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/*
|
|
198
|
+
* If +err+ is non-NULL, copies the message, frees the error struct, and
|
|
199
|
+
* raises a Ruby RuntimeError. Does not return on error.
|
|
200
|
+
*/
|
|
201
|
+
static inline void check_shared_runtime_error(const char *context,
|
|
202
|
+
ddog_SharedRuntimeFFIError *err) {
|
|
203
|
+
if (err == NULL) return;
|
|
204
|
+
|
|
205
|
+
char buf[MAX_RAISE_MESSAGE_SIZE];
|
|
206
|
+
if (err->msg != NULL) {
|
|
207
|
+
snprintf(buf, sizeof(buf), "%s: %s", context, err->msg);
|
|
208
|
+
} else {
|
|
209
|
+
snprintf(buf, sizeof(buf), "%s: (unknown error)", context);
|
|
210
|
+
}
|
|
211
|
+
ddog_shared_runtime_error_free(err);
|
|
212
|
+
raise_error(rb_eRuntimeError, "%s", buf);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* ========================================================================
|
|
216
|
+
* Config helpers
|
|
217
|
+
* ======================================================================== */
|
|
218
|
+
|
|
219
|
+
typedef ddog_TraceExporterError *(*config_setter_fn)(
|
|
220
|
+
ddog_TraceExporterConfig *, ddog_CharSlice);
|
|
221
|
+
|
|
222
|
+
/*
|
|
223
|
+
* Set a single string-valued config field. `rb_val` MUST be a Ruby String
|
|
224
|
+
* (or nil, which is skipped): it is passed to char_slice_from_ruby_string,
|
|
225
|
+
* which enforces the String type. This helper does not handle numeric or
|
|
226
|
+
* other non-string config settings.
|
|
227
|
+
*/
|
|
228
|
+
static inline void set_config_field(
|
|
229
|
+
ddog_TraceExporterConfig *config,
|
|
230
|
+
config_setter_fn setter,
|
|
231
|
+
VALUE rb_val,
|
|
232
|
+
const char *label) {
|
|
233
|
+
if (rb_val == Qnil) return;
|
|
234
|
+
|
|
235
|
+
ddog_TraceExporterError *err =
|
|
236
|
+
setter(config, char_slice_from_ruby_string(rb_val));
|
|
237
|
+
if (err) {
|
|
238
|
+
ddog_trace_exporter_config_free(config);
|
|
239
|
+
check_exporter_error(label, err);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* ========================================================================
|
|
244
|
+
* Conversion helpers (Ruby -> C, require the GVL)
|
|
245
|
+
* ======================================================================== */
|
|
246
|
+
|
|
247
|
+
/* Nullable Ruby String -> ddog_CharSlice (nil -> empty slice) */
|
|
248
|
+
static inline ddog_CharSlice nullable_char_slice(VALUE str) {
|
|
249
|
+
if (str == Qnil) {
|
|
250
|
+
return (ddog_CharSlice){.ptr = "", .len = 0};
|
|
251
|
+
}
|
|
252
|
+
return char_slice_from_ruby_string(str);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* Ruby Time -> int64_t nanoseconds since Unix epoch */
|
|
256
|
+
static inline int64_t time_to_nanos(VALUE time) {
|
|
257
|
+
struct timespec ts = rb_time_timespec(time);
|
|
258
|
+
return (int64_t)ts.tv_sec * 1000000000LL + (int64_t)ts.tv_nsec;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
enum span_event_attribute_type {
|
|
262
|
+
SPAN_EVENT_STRING = 0,
|
|
263
|
+
SPAN_EVENT_BOOL = 1,
|
|
264
|
+
SPAN_EVENT_INT = 2,
|
|
265
|
+
SPAN_EVENT_DOUBLE = 3,
|
|
266
|
+
SPAN_EVENT_ARRAY = 4,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
static inline VALUE event_hash_value(VALUE hash, ID key) {
|
|
270
|
+
return rb_hash_fetch(hash, ID2SYM(key));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Validate one scalar native attribute in place, proving integer values fit
|
|
274
|
+
* the libdatadog wire type before any Rust allocation. */
|
|
275
|
+
static void validate_event_scalar(VALUE key, VALUE attribute, int type) {
|
|
276
|
+
ENFORCE_TYPE(attribute, T_HASH);
|
|
277
|
+
|
|
278
|
+
switch (type) {
|
|
279
|
+
case SPAN_EVENT_STRING:
|
|
280
|
+
ENFORCE_TYPE(event_hash_value(attribute, event_string_value_id), T_STRING);
|
|
281
|
+
break;
|
|
282
|
+
case SPAN_EVENT_BOOL: {
|
|
283
|
+
VALUE value = event_hash_value(attribute, event_bool_value_id);
|
|
284
|
+
if (value != Qtrue && value != Qfalse) {
|
|
285
|
+
private_raise_exception(
|
|
286
|
+
rb_exc_new_str(rb_eTypeError, rb_sprintf(
|
|
287
|
+
"span event attribute '%"PRIsVALUE"' must be true or false, got %s",
|
|
288
|
+
key, rb_obj_classname(value))),
|
|
289
|
+
"span event attribute has invalid boolean value");
|
|
290
|
+
}
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case SPAN_EVENT_INT:
|
|
294
|
+
NUM2LL(event_hash_value(attribute, event_int_value_id));
|
|
295
|
+
break;
|
|
296
|
+
case SPAN_EVENT_DOUBLE:
|
|
297
|
+
NUM2DBL(event_hash_value(attribute, event_double_value_id));
|
|
298
|
+
break;
|
|
299
|
+
default:
|
|
300
|
+
rb_raise(rb_eArgError, "unsupported span event attribute type: %d", type);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/*
|
|
305
|
+
* Build a validated, Ruby-owned snapshot of a span's events for the native
|
|
306
|
+
* exporter. Each SpanEvent is converted via to_native_format, its attributes
|
|
307
|
+
* flattened to [key, hash] pairs, and every scalar/array value type- and
|
|
308
|
+
* range-checked here so a validation failure raises before any Rust
|
|
309
|
+
* allocation. Returns an array of [name, time, pairs] triples consumed by
|
|
310
|
+
* build_native_events; *max_array_length is set to the largest array
|
|
311
|
+
* attribute length, for sizing the conversion scratch buffer.
|
|
312
|
+
*/
|
|
313
|
+
static VALUE normalize_span_events(VALUE span, size_t *max_array_length) {
|
|
314
|
+
VALUE events = rb_ivar_get(span, at_events_id);
|
|
315
|
+
ENFORCE_TYPE(events, T_ARRAY);
|
|
316
|
+
|
|
317
|
+
long event_count = RARRAY_LEN(events);
|
|
318
|
+
VALUE normalized = rb_ary_new_capa(event_count);
|
|
319
|
+
|
|
320
|
+
for (long i = 0; i < event_count; i++) {
|
|
321
|
+
VALUE event = rb_ary_entry(events, i);
|
|
322
|
+
VALUE hash = rb_funcall(event, id_to_native_format, 0);
|
|
323
|
+
ENFORCE_TYPE(hash, T_HASH);
|
|
324
|
+
|
|
325
|
+
VALUE name = rb_hash_fetch(hash, event_name_key);
|
|
326
|
+
VALUE time = rb_hash_fetch(hash, event_time_key);
|
|
327
|
+
ENFORCE_TYPE(name, T_STRING);
|
|
328
|
+
NUM2ULL(time);
|
|
329
|
+
|
|
330
|
+
VALUE attributes = rb_hash_aref(hash, event_attributes_key);
|
|
331
|
+
VALUE pairs = rb_ary_new();
|
|
332
|
+
if (attributes != Qnil) {
|
|
333
|
+
ENFORCE_TYPE(attributes, T_HASH);
|
|
334
|
+
pairs = rb_funcall(attributes, id_to_a, 0);
|
|
335
|
+
|
|
336
|
+
for (long j = 0; j < RARRAY_LEN(pairs); j++) {
|
|
337
|
+
VALUE pair = rb_ary_entry(pairs, j);
|
|
338
|
+
ENFORCE_TYPE(pair, T_ARRAY);
|
|
339
|
+
VALUE key = rb_ary_entry(pair, 0);
|
|
340
|
+
VALUE attribute = rb_ary_entry(pair, 1);
|
|
341
|
+
ENFORCE_TYPE(key, T_STRING);
|
|
342
|
+
ENFORCE_TYPE(attribute, T_HASH);
|
|
343
|
+
|
|
344
|
+
int type = NUM2INT(event_hash_value(attribute, event_type_id));
|
|
345
|
+
if (type != SPAN_EVENT_ARRAY) {
|
|
346
|
+
validate_event_scalar(key, attribute, type);
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
VALUE array_value = event_hash_value(attribute, event_array_value_id);
|
|
351
|
+
ENFORCE_TYPE(array_value, T_HASH);
|
|
352
|
+
VALUE values = event_hash_value(array_value, event_values_id);
|
|
353
|
+
ENFORCE_TYPE(values, T_ARRAY);
|
|
354
|
+
long length = RARRAY_LEN(values);
|
|
355
|
+
if ((size_t)length > *max_array_length) *max_array_length = (size_t)length;
|
|
356
|
+
|
|
357
|
+
int element_type = SPAN_EVENT_STRING;
|
|
358
|
+
if (length > 0) {
|
|
359
|
+
VALUE first = rb_ary_entry(values, 0);
|
|
360
|
+
ENFORCE_TYPE(first, T_HASH);
|
|
361
|
+
element_type = NUM2INT(event_hash_value(first, event_type_id));
|
|
362
|
+
}
|
|
363
|
+
if (element_type == SPAN_EVENT_ARRAY) rb_raise(rb_eArgError, "nested span event arrays are not supported");
|
|
364
|
+
|
|
365
|
+
for (long k = 0; k < length; k++) {
|
|
366
|
+
VALUE value = rb_ary_entry(values, k);
|
|
367
|
+
ENFORCE_TYPE(value, T_HASH);
|
|
368
|
+
int value_type = NUM2INT(event_hash_value(value, event_type_id));
|
|
369
|
+
if (value_type != element_type) rb_raise(rb_eArgError, "span event arrays must be homogeneous");
|
|
370
|
+
validate_event_scalar(key, value, value_type);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
rb_ary_push(normalized, rb_ary_new_from_args(3, name, time, pairs));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return normalized;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* 128-bit trace ID split into two 64-bit halves */
|
|
382
|
+
typedef struct {
|
|
383
|
+
uint64_t low;
|
|
384
|
+
uint64_t high;
|
|
385
|
+
} trace_id_t;
|
|
386
|
+
|
|
387
|
+
/* Ruby 128-bit Integer -> trace_id_t */
|
|
388
|
+
static inline trace_id_t split_trace_id(VALUE trace_id) {
|
|
389
|
+
/* Fast path: Fixnum fits in 63 bits, no high half */
|
|
390
|
+
if (FIXNUM_P(trace_id)) {
|
|
391
|
+
return (trace_id_t){
|
|
392
|
+
.low = (uint64_t)FIX2LONG(trace_id),
|
|
393
|
+
.high = 0,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/* Bignum path: extract raw bytes into two 64-bit words */
|
|
398
|
+
unsigned long words[2] = {0, 0};
|
|
399
|
+
rb_big_pack(trace_id, words, 2);
|
|
400
|
+
return (trace_id_t){
|
|
401
|
+
.low = (uint64_t)words[0],
|
|
402
|
+
.high = (uint64_t)words[1],
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/* ========================================================================
|
|
407
|
+
* Hash iteration callbacks for meta / metrics
|
|
408
|
+
*
|
|
409
|
+
* The libdatadog setters return owned errors rather than raising. Stash the
|
|
410
|
+
* first error in a context struct and stop iteration with ST_STOP so the
|
|
411
|
+
* caller can free the still-unowned Rust span before turning the error into
|
|
412
|
+
* a Ruby exception. (This is about span ownership, not hash iteration: MRI
|
|
413
|
+
* restores rb_hash_foreach's iteration state via rb_ensure if a callback
|
|
414
|
+
* exits non-locally.)
|
|
415
|
+
* ======================================================================== */
|
|
416
|
+
|
|
417
|
+
typedef struct {
|
|
418
|
+
ddog_TracerSpan *span;
|
|
419
|
+
ddog_TraceExporterError *error; /* first error, if any */
|
|
420
|
+
long skipped; /* entries skipped due to wrong type */
|
|
421
|
+
} hash_iter_ctx;
|
|
422
|
+
|
|
423
|
+
static int meta_iter_cb(VALUE key, VALUE value, VALUE arg) {
|
|
424
|
+
hash_iter_ctx *ctx = (hash_iter_ctx *)arg;
|
|
425
|
+
|
|
426
|
+
/*
|
|
427
|
+
* The types are checked below, so build the ddog_CharSlice directly instead
|
|
428
|
+
* of repeating char_slice_from_ruby_string()'s ENFORCE_TYPE check.
|
|
429
|
+
* libdatadog copies both slices before the FFI call returns and retains no
|
|
430
|
+
* pointer into the Ruby-owned string storage.
|
|
431
|
+
*/
|
|
432
|
+
if (!RB_TYPE_P(key, T_STRING) || !RB_TYPE_P(value, T_STRING)) {
|
|
433
|
+
ctx->skipped++;
|
|
434
|
+
return ST_CONTINUE;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
ddog_CharSlice ks = {.ptr = RSTRING_PTR(key), .len = RSTRING_LEN(key)};
|
|
438
|
+
ddog_CharSlice vs = {.ptr = RSTRING_PTR(value), .len = RSTRING_LEN(value)};
|
|
439
|
+
|
|
440
|
+
ddog_TraceExporterError *err = ddog_tracer_span_set_meta(ctx->span, ks, vs);
|
|
441
|
+
if (err != NULL) {
|
|
442
|
+
ctx->error = err;
|
|
443
|
+
return ST_STOP;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return ST_CONTINUE;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
static int metrics_iter_cb(VALUE key, VALUE value, VALUE arg) {
|
|
450
|
+
hash_iter_ctx *ctx = (hash_iter_ctx *)arg;
|
|
451
|
+
|
|
452
|
+
if (!RB_TYPE_P(key, T_STRING) ||
|
|
453
|
+
(!RB_TYPE_P(value, T_FLOAT) && !RB_TYPE_P(value, T_FIXNUM) &&
|
|
454
|
+
!RB_TYPE_P(value, T_BIGNUM))) {
|
|
455
|
+
ctx->skipped++;
|
|
456
|
+
return ST_CONTINUE;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* See meta_iter_cb: the key type is checked above, so build the slice
|
|
460
|
+
* directly. */
|
|
461
|
+
ddog_CharSlice ks = {.ptr = RSTRING_PTR(key), .len = RSTRING_LEN(key)};
|
|
462
|
+
|
|
463
|
+
ddog_TraceExporterError *err =
|
|
464
|
+
ddog_tracer_span_set_metric(ctx->span, ks, NUM2DBL(value));
|
|
465
|
+
if (err != NULL) {
|
|
466
|
+
ctx->error = err;
|
|
467
|
+
return ST_STOP;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return ST_CONTINUE;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
typedef struct {
|
|
474
|
+
VALUE span;
|
|
475
|
+
VALUE normalized_events;
|
|
476
|
+
raw_span_owner *owner;
|
|
477
|
+
void *allocation;
|
|
478
|
+
void *array_scratch;
|
|
479
|
+
ddog_TracerSpanEvent **events;
|
|
480
|
+
long event_count;
|
|
481
|
+
size_t max_array_length;
|
|
482
|
+
} span_conversion_ctx;
|
|
483
|
+
|
|
484
|
+
typedef union {
|
|
485
|
+
ddog_CharSlice string;
|
|
486
|
+
bool boolean;
|
|
487
|
+
int64_t integer;
|
|
488
|
+
double double_value;
|
|
489
|
+
} span_event_array_scratch;
|
|
490
|
+
|
|
491
|
+
typedef struct {
|
|
492
|
+
char padding;
|
|
493
|
+
span_event_array_scratch value;
|
|
494
|
+
} span_event_array_scratch_alignment;
|
|
495
|
+
|
|
496
|
+
/* Free event resources that the conversion context still owns at cleanup
|
|
497
|
+
* time. build_native_events allocates each event into ctx->events[i];
|
|
498
|
+
* build_rust_span transfers ownership to the Rust span via add_event and
|
|
499
|
+
* NULLs the slot. Events left non-NULL here were never attached (an
|
|
500
|
+
* exception interrupted build_rust_span) and are freed now. The raw span
|
|
501
|
+
* itself is owned by the caller's separate ensure handler. */
|
|
502
|
+
static VALUE free_span_conversion(VALUE arg) {
|
|
503
|
+
span_conversion_ctx *ctx = (span_conversion_ctx *)arg;
|
|
504
|
+
if (ctx->events != NULL) {
|
|
505
|
+
for (long i = 0; i < ctx->event_count; i++) {
|
|
506
|
+
if (ctx->events[i] != NULL) {
|
|
507
|
+
ddog_tracer_span_event_free(ctx->events[i]);
|
|
508
|
+
ctx->events[i] = NULL;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (ctx->allocation != NULL) {
|
|
513
|
+
ruby_xfree(ctx->allocation);
|
|
514
|
+
ctx->allocation = NULL;
|
|
515
|
+
ctx->events = NULL;
|
|
516
|
+
ctx->array_scratch = NULL;
|
|
517
|
+
}
|
|
518
|
+
return Qnil;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/* Attach one normalized Ruby attribute to an event. Unknown type codes are
|
|
522
|
+
* unreachable because normalize_span_events already rejected them. */
|
|
523
|
+
static ddog_TraceExporterError *set_native_event_attribute(
|
|
524
|
+
ddog_TracerSpanEvent *event,
|
|
525
|
+
VALUE key,
|
|
526
|
+
VALUE attribute,
|
|
527
|
+
void *scratch) {
|
|
528
|
+
ddog_CharSlice key_slice = char_slice_from_ruby_string(key);
|
|
529
|
+
int type = NUM2INT(event_hash_value(attribute, event_type_id));
|
|
530
|
+
|
|
531
|
+
switch (type) {
|
|
532
|
+
case SPAN_EVENT_STRING:
|
|
533
|
+
return ddog_tracer_span_event_set_string(
|
|
534
|
+
event, key_slice,
|
|
535
|
+
char_slice_from_ruby_string(event_hash_value(attribute, event_string_value_id)));
|
|
536
|
+
case SPAN_EVENT_BOOL:
|
|
537
|
+
return ddog_tracer_span_event_set_bool(
|
|
538
|
+
event, key_slice,
|
|
539
|
+
event_hash_value(attribute, event_bool_value_id) == Qtrue);
|
|
540
|
+
case SPAN_EVENT_INT:
|
|
541
|
+
return ddog_tracer_span_event_set_int(
|
|
542
|
+
event, key_slice,
|
|
543
|
+
NUM2LL(event_hash_value(attribute, event_int_value_id)));
|
|
544
|
+
case SPAN_EVENT_DOUBLE:
|
|
545
|
+
return ddog_tracer_span_event_set_double(
|
|
546
|
+
event, key_slice,
|
|
547
|
+
NUM2DBL(event_hash_value(attribute, event_double_value_id)));
|
|
548
|
+
case SPAN_EVENT_ARRAY:
|
|
549
|
+
break;
|
|
550
|
+
default:
|
|
551
|
+
return NULL;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
VALUE array_value = event_hash_value(attribute, event_array_value_id);
|
|
555
|
+
VALUE values = event_hash_value(array_value, event_values_id);
|
|
556
|
+
long length = RARRAY_LEN(values);
|
|
557
|
+
int element_type = SPAN_EVENT_STRING;
|
|
558
|
+
if (length > 0) {
|
|
559
|
+
element_type = NUM2INT(event_hash_value(rb_ary_entry(values, 0), event_type_id));
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
switch (element_type) {
|
|
563
|
+
case SPAN_EVENT_STRING: {
|
|
564
|
+
ddog_CharSlice *out = (ddog_CharSlice *)scratch;
|
|
565
|
+
for (long i = 0; i < length; i++) {
|
|
566
|
+
VALUE value = event_hash_value(rb_ary_entry(values, i), event_string_value_id);
|
|
567
|
+
out[i] = char_slice_from_ruby_string(value);
|
|
568
|
+
}
|
|
569
|
+
return ddog_tracer_span_event_set_string_array(
|
|
570
|
+
event, key_slice,
|
|
571
|
+
(struct ddog_Slice_CharSlice){.ptr = out, .len = (uintptr_t)length});
|
|
572
|
+
}
|
|
573
|
+
case SPAN_EVENT_BOOL: {
|
|
574
|
+
bool *out = (bool *)scratch;
|
|
575
|
+
for (long i = 0; i < length; i++) {
|
|
576
|
+
out[i] = event_hash_value(rb_ary_entry(values, i), event_bool_value_id) == Qtrue;
|
|
577
|
+
}
|
|
578
|
+
return ddog_tracer_span_event_set_bool_array(
|
|
579
|
+
event, key_slice,
|
|
580
|
+
(struct ddog_Slice_Bool){.ptr = out, .len = (uintptr_t)length});
|
|
581
|
+
}
|
|
582
|
+
case SPAN_EVENT_INT: {
|
|
583
|
+
int64_t *out = (int64_t *)scratch;
|
|
584
|
+
for (long i = 0; i < length; i++) {
|
|
585
|
+
out[i] = NUM2LL(event_hash_value(rb_ary_entry(values, i), event_int_value_id));
|
|
586
|
+
}
|
|
587
|
+
return ddog_tracer_span_event_set_int_array(
|
|
588
|
+
event, key_slice,
|
|
589
|
+
(struct ddog_Slice_I64){.ptr = out, .len = (uintptr_t)length});
|
|
590
|
+
}
|
|
591
|
+
case SPAN_EVENT_DOUBLE: {
|
|
592
|
+
double *out = (double *)scratch;
|
|
593
|
+
for (long i = 0; i < length; i++) {
|
|
594
|
+
out[i] = NUM2DBL(event_hash_value(rb_ary_entry(values, i), event_double_value_id));
|
|
595
|
+
}
|
|
596
|
+
return ddog_tracer_span_event_set_double_array(
|
|
597
|
+
event, key_slice,
|
|
598
|
+
(struct ddog_Slice_F64){.ptr = out, .len = (uintptr_t)length});
|
|
599
|
+
}
|
|
600
|
+
default:
|
|
601
|
+
return NULL;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/* Build every normalized event before constructing its owning span. The
|
|
606
|
+
* conversion context retains each event until add_event consumes it. */
|
|
607
|
+
static void build_native_events(span_conversion_ctx *ctx) {
|
|
608
|
+
for (long i = 0; i < ctx->event_count; i++) {
|
|
609
|
+
VALUE source = rb_ary_entry(ctx->normalized_events, i);
|
|
610
|
+
ddog_TraceExporterError *err = ddog_tracer_span_event_new(
|
|
611
|
+
&ctx->events[i],
|
|
612
|
+
char_slice_from_ruby_string(rb_ary_entry(source, 0)),
|
|
613
|
+
NUM2ULL(rb_ary_entry(source, 1)));
|
|
614
|
+
check_exporter_error("Failed to create span event", err);
|
|
615
|
+
|
|
616
|
+
VALUE pairs = rb_ary_entry(source, 2);
|
|
617
|
+
for (long j = 0; j < RARRAY_LEN(pairs); j++) {
|
|
618
|
+
VALUE pair = rb_ary_entry(pairs, j);
|
|
619
|
+
err = set_native_event_attribute(
|
|
620
|
+
ctx->events[i], rb_ary_entry(pair, 0), rb_ary_entry(pair, 1), ctx->array_scratch);
|
|
621
|
+
check_exporter_error("Failed to set span event attribute", err);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
typedef struct {
|
|
627
|
+
char *ptr;
|
|
628
|
+
size_t len;
|
|
629
|
+
} owned_link_string;
|
|
630
|
+
|
|
631
|
+
typedef struct {
|
|
632
|
+
owned_link_string key;
|
|
633
|
+
owned_link_string value;
|
|
634
|
+
} owned_link_attribute;
|
|
635
|
+
|
|
636
|
+
typedef struct {
|
|
637
|
+
uint64_t trace_id_low;
|
|
638
|
+
uint64_t trace_id_high;
|
|
639
|
+
uint64_t span_id;
|
|
640
|
+
owned_link_attribute *attributes;
|
|
641
|
+
size_t attribute_count;
|
|
642
|
+
owned_link_string tracestate;
|
|
643
|
+
uint32_t flags;
|
|
644
|
+
} owned_span_link;
|
|
645
|
+
|
|
646
|
+
typedef struct {
|
|
647
|
+
VALUE rb_links;
|
|
648
|
+
owned_span_link *links;
|
|
649
|
+
size_t link_count;
|
|
650
|
+
size_t attribute_count;
|
|
651
|
+
void *ffi_storage;
|
|
652
|
+
ddog_TracerSpanLink *ffi_links;
|
|
653
|
+
} span_links_snapshot;
|
|
654
|
+
|
|
655
|
+
typedef struct {
|
|
656
|
+
owned_link_attribute *attributes;
|
|
657
|
+
size_t offset;
|
|
658
|
+
size_t capacity;
|
|
659
|
+
} snapshot_attribute_ctx;
|
|
660
|
+
|
|
661
|
+
/* SpanLink#to_hash stringifies attribute values and yields tracestate as a
|
|
662
|
+
* String; enforce T_STRING here so a non-String surfaces as a type error at
|
|
663
|
+
* the boundary. */
|
|
664
|
+
static void snapshot_link_string(VALUE string, owned_link_string *snapshot) {
|
|
665
|
+
ENFORCE_TYPE(string, T_STRING);
|
|
666
|
+
snapshot->len = (size_t)RSTRING_LEN(string);
|
|
667
|
+
snapshot->ptr = ruby_xmalloc(snapshot->len == 0 ? 1 : snapshot->len);
|
|
668
|
+
if (snapshot->len > 0) {
|
|
669
|
+
memcpy(snapshot->ptr, RSTRING_PTR(string), snapshot->len);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
static int snapshot_link_attribute_cb(VALUE key, VALUE value, VALUE arg) {
|
|
674
|
+
snapshot_attribute_ctx *ctx = (snapshot_attribute_ctx *)arg;
|
|
675
|
+
if (ctx->offset >= ctx->capacity) {
|
|
676
|
+
raise_error(rb_eRuntimeError, "Span link attributes changed during snapshot");
|
|
677
|
+
}
|
|
678
|
+
owned_link_attribute *attribute = &ctx->attributes[ctx->offset++];
|
|
679
|
+
snapshot_link_string(key, &attribute->key);
|
|
680
|
+
snapshot_link_string(value, &attribute->value);
|
|
681
|
+
return ST_CONTINUE;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
static ddog_CharSlice snapshot_char_slice(const owned_link_string *snapshot) {
|
|
685
|
+
return (ddog_CharSlice){
|
|
686
|
+
.ptr = snapshot->ptr == NULL ? "" : snapshot->ptr,
|
|
687
|
+
.len = snapshot->len,
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
static void free_owned_link_string(owned_link_string *snapshot) {
|
|
692
|
+
if (snapshot->ptr != NULL) {
|
|
693
|
+
ruby_xfree(snapshot->ptr);
|
|
694
|
+
snapshot->ptr = NULL;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
static void free_span_links_snapshot(span_links_snapshot *snapshot) {
|
|
699
|
+
if (snapshot->ffi_storage != NULL) {
|
|
700
|
+
ruby_xfree(snapshot->ffi_storage);
|
|
701
|
+
}
|
|
702
|
+
snapshot->ffi_storage = NULL;
|
|
703
|
+
snapshot->ffi_links = NULL;
|
|
704
|
+
|
|
705
|
+
if (snapshot->links != NULL) {
|
|
706
|
+
for (size_t i = 0; i < snapshot->link_count; i++) {
|
|
707
|
+
owned_span_link *link = &snapshot->links[i];
|
|
708
|
+
if (link->attributes != NULL) {
|
|
709
|
+
for (size_t j = 0; j < link->attribute_count; j++) {
|
|
710
|
+
free_owned_link_string(&link->attributes[j].key);
|
|
711
|
+
free_owned_link_string(&link->attributes[j].value);
|
|
712
|
+
}
|
|
713
|
+
ruby_xfree(link->attributes);
|
|
714
|
+
}
|
|
715
|
+
free_owned_link_string(&link->tracestate);
|
|
716
|
+
}
|
|
717
|
+
ruby_xfree(snapshot->links);
|
|
718
|
+
snapshot->links = NULL;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
static VALUE prepare_span_links_snapshot(VALUE arg) {
|
|
723
|
+
span_links_snapshot *snapshot = (span_links_snapshot *)arg;
|
|
724
|
+
snapshot->link_count = (size_t)RARRAY_LEN(snapshot->rb_links);
|
|
725
|
+
if (snapshot->link_count > SIZE_MAX / sizeof(owned_span_link)) {
|
|
726
|
+
raise_error(rb_eArgError, "Span link count is too large");
|
|
727
|
+
}
|
|
728
|
+
if (snapshot->link_count > 0) {
|
|
729
|
+
snapshot->links = ruby_xcalloc(snapshot->link_count, sizeof(owned_span_link));
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
for (size_t i = 0; i < snapshot->link_count; i++) {
|
|
733
|
+
VALUE canonical = rb_funcall(rb_ary_entry(snapshot->rb_links, (long)i), id_to_hash, 0);
|
|
734
|
+
ENFORCE_TYPE(canonical, T_HASH);
|
|
735
|
+
|
|
736
|
+
/* Fetch each canonical field exactly once. Hash default procs may be
|
|
737
|
+
* stateful, so every value must be captured before Rust allocation/FFI. */
|
|
738
|
+
owned_span_link *link = &snapshot->links[i];
|
|
739
|
+
VALUE trace_id = rb_hash_aref(canonical, ID2SYM(link_trace_id_id));
|
|
740
|
+
link->trace_id_low = NUM2ULL(trace_id);
|
|
741
|
+
|
|
742
|
+
VALUE trace_id_high = rb_hash_aref(canonical, ID2SYM(link_trace_id_high_id));
|
|
743
|
+
link->trace_id_high = trace_id_high == Qnil ? 0 : NUM2ULL(trace_id_high);
|
|
744
|
+
|
|
745
|
+
VALUE span_id = rb_hash_aref(canonical, ID2SYM(link_span_id_id));
|
|
746
|
+
link->span_id = NUM2ULL(span_id);
|
|
747
|
+
|
|
748
|
+
VALUE attributes = rb_hash_aref(canonical, ID2SYM(link_attributes_id));
|
|
749
|
+
if (attributes != Qnil) {
|
|
750
|
+
ENFORCE_TYPE(attributes, T_HASH);
|
|
751
|
+
link->attribute_count = (size_t)RHASH_SIZE(attributes);
|
|
752
|
+
if (link->attribute_count > SIZE_MAX - snapshot->attribute_count) {
|
|
753
|
+
raise_error(rb_eArgError, "Span link attribute count is too large");
|
|
754
|
+
}
|
|
755
|
+
snapshot->attribute_count += link->attribute_count;
|
|
756
|
+
if (link->attribute_count > 0) {
|
|
757
|
+
link->attributes = ruby_xcalloc(link->attribute_count, sizeof(owned_link_attribute));
|
|
758
|
+
snapshot_attribute_ctx ctx = {
|
|
759
|
+
.attributes = link->attributes,
|
|
760
|
+
.offset = 0,
|
|
761
|
+
.capacity = link->attribute_count,
|
|
762
|
+
};
|
|
763
|
+
rb_hash_foreach(attributes, snapshot_link_attribute_cb, (VALUE)&ctx);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
VALUE tracestate = rb_hash_aref(canonical, ID2SYM(link_tracestate_id));
|
|
768
|
+
if (tracestate != Qnil) {
|
|
769
|
+
snapshot_link_string(tracestate, &link->tracestate);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
VALUE flags = rb_hash_aref(canonical, ID2SYM(link_flags_id));
|
|
773
|
+
link->flags = NUM2UINT(flags);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (snapshot->attribute_count > SIZE_MAX / sizeof(ddog_TracerSpanLinkAttribute)) {
|
|
777
|
+
raise_error(rb_eArgError, "Span link attribute count is too large");
|
|
778
|
+
}
|
|
779
|
+
size_t attributes_size =
|
|
780
|
+
snapshot->attribute_count * sizeof(ddog_TracerSpanLinkAttribute);
|
|
781
|
+
if (snapshot->link_count > (SIZE_MAX - attributes_size) /
|
|
782
|
+
sizeof(ddog_TracerSpanLink)) {
|
|
783
|
+
raise_error(rb_eArgError, "Span link count is too large");
|
|
784
|
+
}
|
|
785
|
+
size_t links_size = snapshot->link_count * sizeof(ddog_TracerSpanLink);
|
|
786
|
+
size_t storage_size = links_size + attributes_size;
|
|
787
|
+
snapshot->ffi_storage = ruby_xcalloc(1, storage_size == 0 ? 1 : storage_size);
|
|
788
|
+
snapshot->ffi_links = (ddog_TracerSpanLink *)snapshot->ffi_storage;
|
|
789
|
+
ddog_TracerSpanLinkAttribute *ffi_attributes =
|
|
790
|
+
(ddog_TracerSpanLinkAttribute *)((char *)snapshot->ffi_storage + links_size);
|
|
791
|
+
size_t attribute_offset = 0;
|
|
792
|
+
|
|
793
|
+
for (size_t i = 0; i < snapshot->link_count; i++) {
|
|
794
|
+
owned_span_link *link = &snapshot->links[i];
|
|
795
|
+
size_t first_attribute = attribute_offset;
|
|
796
|
+
for (size_t j = 0; j < link->attribute_count; j++) {
|
|
797
|
+
owned_link_attribute *attribute = &link->attributes[j];
|
|
798
|
+
ffi_attributes[attribute_offset++] = (ddog_TracerSpanLinkAttribute){
|
|
799
|
+
.key = snapshot_char_slice(&attribute->key),
|
|
800
|
+
.value = snapshot_char_slice(&attribute->value),
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
snapshot->ffi_links[i] = (ddog_TracerSpanLink){
|
|
804
|
+
.trace_id_low = link->trace_id_low,
|
|
805
|
+
.trace_id_high = link->trace_id_high,
|
|
806
|
+
.span_id = link->span_id,
|
|
807
|
+
.attributes = {
|
|
808
|
+
.ptr = ffi_attributes + first_attribute,
|
|
809
|
+
.len = link->attribute_count,
|
|
810
|
+
},
|
|
811
|
+
.tracestate = snapshot_char_slice(&link->tracestate),
|
|
812
|
+
.flags = link->flags,
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
return Qnil;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
typedef struct {
|
|
820
|
+
ddog_TracerValueToken *tokens;
|
|
821
|
+
size_t len;
|
|
822
|
+
size_t capacity;
|
|
823
|
+
st_table *active;
|
|
824
|
+
uint8_t **scratch;
|
|
825
|
+
size_t scratch_len;
|
|
826
|
+
size_t scratch_capacity;
|
|
827
|
+
} structured_value_ctx;
|
|
828
|
+
|
|
829
|
+
static ddog_TracerValueToken *append_structured_value_token(
|
|
830
|
+
structured_value_ctx *ctx, uint8_t kind) {
|
|
831
|
+
if (ctx->len == ctx->capacity) {
|
|
832
|
+
size_t capacity = ctx->capacity == 0 ? 16 : ctx->capacity * 2;
|
|
833
|
+
if (capacity < ctx->capacity || capacity > SIZE_MAX / sizeof(*ctx->tokens)) {
|
|
834
|
+
rb_raise(rb_eNoMemError, "meta_struct token buffer is too large");
|
|
835
|
+
}
|
|
836
|
+
REALLOC_N(ctx->tokens, ddog_TracerValueToken, capacity);
|
|
837
|
+
ctx->capacity = capacity;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
ddog_TracerValueToken *token = &ctx->tokens[ctx->len++];
|
|
841
|
+
*token = (ddog_TracerValueToken){0};
|
|
842
|
+
token->kind = kind;
|
|
843
|
+
return token;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
static const uint8_t *copy_structured_value_bytes(
|
|
847
|
+
structured_value_ctx *ctx, VALUE string, size_t len) {
|
|
848
|
+
if (len == 0) return (const uint8_t *)"";
|
|
849
|
+
|
|
850
|
+
if (ctx->scratch_len == ctx->scratch_capacity) {
|
|
851
|
+
size_t capacity = ctx->scratch_capacity == 0 ? 8 : ctx->scratch_capacity * 2;
|
|
852
|
+
if (capacity < ctx->scratch_capacity || capacity > SIZE_MAX / sizeof(*ctx->scratch)) {
|
|
853
|
+
rb_raise(rb_eNoMemError, "meta_struct scratch buffer is too large");
|
|
854
|
+
}
|
|
855
|
+
REALLOC_N(ctx->scratch, uint8_t *, capacity);
|
|
856
|
+
ctx->scratch_capacity = capacity;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
uint8_t *copy = ruby_xmalloc(len);
|
|
860
|
+
ctx->scratch[ctx->scratch_len++] = copy;
|
|
861
|
+
/* ruby_xmalloc may trigger GC, so retrieve the Ruby buffer only after it
|
|
862
|
+
* returns and do not call Ruby again before the copy completes. */
|
|
863
|
+
memcpy(copy, RSTRING_PTR(string), len);
|
|
864
|
+
return copy;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
static void free_structured_value_ctx(structured_value_ctx *ctx) {
|
|
868
|
+
if (ctx->active != NULL) st_free_table(ctx->active);
|
|
869
|
+
for (size_t i = 0; i < ctx->scratch_len; i++) {
|
|
870
|
+
ruby_xfree(ctx->scratch[i]);
|
|
871
|
+
}
|
|
872
|
+
ruby_xfree(ctx->scratch);
|
|
873
|
+
ruby_xfree(ctx->tokens);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
static VALUE resolve_serializable_backtrace_class(void) {
|
|
877
|
+
if (serializable_backtrace_class != Qnil) return serializable_backtrace_class;
|
|
878
|
+
|
|
879
|
+
ID datadog_id = rb_intern("Datadog");
|
|
880
|
+
ID appsec_id = rb_intern("AppSec");
|
|
881
|
+
ID actions_handler_id = rb_intern("ActionsHandler");
|
|
882
|
+
ID backtrace_id = rb_intern("SerializableBacktrace");
|
|
883
|
+
if (!rb_const_defined(rb_cObject, datadog_id)) return Qnil;
|
|
884
|
+
VALUE datadog = rb_const_get(rb_cObject, datadog_id);
|
|
885
|
+
if (!rb_const_defined(datadog, appsec_id)) return Qnil;
|
|
886
|
+
VALUE appsec = rb_const_get(datadog, appsec_id);
|
|
887
|
+
if (!rb_const_defined(appsec, actions_handler_id)) return Qnil;
|
|
888
|
+
VALUE actions_handler = rb_const_get(appsec, actions_handler_id);
|
|
889
|
+
if (!rb_const_defined(actions_handler, backtrace_id)) return Qnil;
|
|
890
|
+
|
|
891
|
+
serializable_backtrace_class = rb_const_get(actions_handler, backtrace_id);
|
|
892
|
+
rb_global_variable(&serializable_backtrace_class);
|
|
893
|
+
return serializable_backtrace_class;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
static void append_structured_value(VALUE value, unsigned int depth,
|
|
897
|
+
structured_value_ctx *ctx);
|
|
898
|
+
|
|
899
|
+
typedef struct {
|
|
900
|
+
structured_value_ctx *ctx;
|
|
901
|
+
unsigned int depth;
|
|
902
|
+
} structured_hash_ctx;
|
|
903
|
+
|
|
904
|
+
static int append_structured_hash_entry(VALUE key, VALUE value, VALUE arg) {
|
|
905
|
+
structured_hash_ctx *hash_ctx = (structured_hash_ctx *)arg;
|
|
906
|
+
append_structured_value(key, hash_ctx->depth, hash_ctx->ctx);
|
|
907
|
+
append_structured_value(value, hash_ctx->depth, hash_ctx->ctx);
|
|
908
|
+
return ST_CONTINUE;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
static VALUE utf8_string(VALUE value) {
|
|
912
|
+
VALUE string = RB_TYPE_P(value, T_SYMBOL) ? rb_sym2str(value) : value;
|
|
913
|
+
string = rb_str_export_to_enc(string, rb_utf8_encoding());
|
|
914
|
+
if (rb_enc_str_coderange(string) == ENC_CODERANGE_BROKEN) {
|
|
915
|
+
rb_raise(rb_eEncodingError, "meta_struct string is not valid UTF-8");
|
|
916
|
+
}
|
|
917
|
+
return string;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
static void append_structured_value(VALUE value, unsigned int depth,
|
|
921
|
+
structured_value_ctx *ctx) {
|
|
922
|
+
if (value == Qnil) {
|
|
923
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_NIL);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (value == Qtrue || value == Qfalse) {
|
|
927
|
+
ddog_TracerValueToken *token =
|
|
928
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_BOOL);
|
|
929
|
+
token->bool_value = value == Qtrue ? 1 : 0;
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
if (RB_TYPE_P(value, T_FIXNUM) || RB_TYPE_P(value, T_BIGNUM)) {
|
|
933
|
+
if (RTEST(rb_funcall(value, id_negative_p, 0))) {
|
|
934
|
+
ddog_TracerValueToken *token =
|
|
935
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_I64);
|
|
936
|
+
token->i64_value = NUM2LL(value);
|
|
937
|
+
} else {
|
|
938
|
+
ddog_TracerValueToken *token =
|
|
939
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_U64);
|
|
940
|
+
token->u64_value = NUM2ULL(value);
|
|
941
|
+
}
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
if (RB_TYPE_P(value, T_FLOAT)) {
|
|
945
|
+
ddog_TracerValueToken *token =
|
|
946
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_F64);
|
|
947
|
+
token->f64_value = RFLOAT_VALUE(value);
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
if (RB_TYPE_P(value, T_STRING) || RB_TYPE_P(value, T_SYMBOL)) {
|
|
951
|
+
bool binary = RB_TYPE_P(value, T_STRING) &&
|
|
952
|
+
rb_enc_get_index(value) == rb_ascii8bit_encindex();
|
|
953
|
+
VALUE string = binary ? value : utf8_string(value);
|
|
954
|
+
size_t len = (size_t)RSTRING_LEN(string);
|
|
955
|
+
ddog_TracerValueToken *token = append_structured_value_token(
|
|
956
|
+
ctx, binary ? DDOG_TRACER_VALUE_BINARY : DDOG_TRACER_VALUE_STRING);
|
|
957
|
+
token->bytes = (ddog_ByteSlice){
|
|
958
|
+
.ptr = copy_structured_value_bytes(ctx, string, len),
|
|
959
|
+
.len = len,
|
|
960
|
+
};
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
VALUE backtrace_class = resolve_serializable_backtrace_class();
|
|
965
|
+
if (backtrace_class != Qnil && rb_obj_is_kind_of(value, backtrace_class)) {
|
|
966
|
+
append_structured_value(rb_funcall(value, id_to_h, 0), depth, ctx);
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
if (!RB_TYPE_P(value, T_ARRAY) && !RB_TYPE_P(value, T_HASH)) {
|
|
971
|
+
rb_raise(rb_eTypeError, "unsupported meta_struct value type: %s",
|
|
972
|
+
rb_obj_classname(value));
|
|
973
|
+
}
|
|
974
|
+
if (depth >= 64) {
|
|
975
|
+
rb_raise(rb_eArgError, "meta_struct value exceeds maximum depth of 64");
|
|
976
|
+
}
|
|
977
|
+
if (st_lookup(ctx->active, (st_data_t)value, NULL)) {
|
|
978
|
+
rb_raise(rb_eArgError, "meta_struct value contains a cycle");
|
|
979
|
+
}
|
|
980
|
+
st_insert(ctx->active, (st_data_t)value, 1);
|
|
981
|
+
|
|
982
|
+
size_t length = RB_TYPE_P(value, T_ARRAY) ? (size_t)RARRAY_LEN(value) : RHASH_SIZE(value);
|
|
983
|
+
if (length > UINT32_MAX) {
|
|
984
|
+
rb_raise(rb_eArgError, "meta_struct container exceeds u32::MAX entries");
|
|
985
|
+
}
|
|
986
|
+
ddog_TracerValueToken *token = append_structured_value_token(
|
|
987
|
+
ctx, RB_TYPE_P(value, T_ARRAY) ? DDOG_TRACER_VALUE_ARRAY : DDOG_TRACER_VALUE_MAP);
|
|
988
|
+
token->child_count = (uint32_t)length;
|
|
989
|
+
|
|
990
|
+
if (RB_TYPE_P(value, T_ARRAY)) {
|
|
991
|
+
for (size_t i = 0; i < length; i++) {
|
|
992
|
+
append_structured_value(rb_ary_entry(value, (long)i), depth + 1, ctx);
|
|
993
|
+
}
|
|
994
|
+
} else {
|
|
995
|
+
structured_hash_ctx hash_ctx = {.ctx = ctx, .depth = depth + 1};
|
|
996
|
+
rb_hash_foreach(value, append_structured_hash_entry, (VALUE)&hash_ctx);
|
|
997
|
+
}
|
|
998
|
+
st_delete(ctx->active, (st_data_t *)&value, NULL);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
typedef struct {
|
|
1002
|
+
const uint8_t *key;
|
|
1003
|
+
size_t key_len;
|
|
1004
|
+
structured_value_ctx value;
|
|
1005
|
+
} prepared_metastruct_entry;
|
|
1006
|
+
|
|
1007
|
+
typedef struct {
|
|
1008
|
+
prepared_metastruct_entry *entries;
|
|
1009
|
+
size_t len;
|
|
1010
|
+
size_t capacity;
|
|
1011
|
+
} prepared_metastruct;
|
|
1012
|
+
|
|
1013
|
+
static void free_prepared_metastruct(prepared_metastruct *prepared) {
|
|
1014
|
+
for (size_t i = 0; i < prepared->len; i++) {
|
|
1015
|
+
free_structured_value_ctx(&prepared->entries[i].value);
|
|
1016
|
+
}
|
|
1017
|
+
ruby_xfree(prepared->entries);
|
|
1018
|
+
*prepared = (prepared_metastruct){0};
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
static prepared_metastruct_entry *append_prepared_metastruct_entry(
|
|
1022
|
+
prepared_metastruct *prepared) {
|
|
1023
|
+
if (prepared->len == prepared->capacity) {
|
|
1024
|
+
size_t capacity = prepared->capacity == 0 ? 4 : prepared->capacity * 2;
|
|
1025
|
+
if (capacity < prepared->capacity || capacity > SIZE_MAX / sizeof(*prepared->entries)) {
|
|
1026
|
+
rb_raise(rb_eNoMemError, "meta_struct entry buffer is too large");
|
|
1027
|
+
}
|
|
1028
|
+
REALLOC_N(prepared->entries, prepared_metastruct_entry, capacity);
|
|
1029
|
+
prepared->capacity = capacity;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
prepared_metastruct_entry *entry = &prepared->entries[prepared->len++];
|
|
1033
|
+
*entry = (prepared_metastruct_entry){0};
|
|
1034
|
+
entry->value.active = st_init_numtable();
|
|
1035
|
+
return entry;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
typedef struct {
|
|
1039
|
+
prepared_metastruct *prepared;
|
|
1040
|
+
long skipped;
|
|
1041
|
+
} metastruct_prepare_ctx;
|
|
1042
|
+
|
|
1043
|
+
static int prepare_metastruct_iter_cb(VALUE key, VALUE value, VALUE arg) {
|
|
1044
|
+
metastruct_prepare_ctx *ctx = (metastruct_prepare_ctx *)arg;
|
|
1045
|
+
|
|
1046
|
+
/* The agent meta_struct contract requires string keys. Accept symbols as a
|
|
1047
|
+
* Ruby convenience, but do not encode other key types differently from the
|
|
1048
|
+
* native tracer implementations. */
|
|
1049
|
+
if (RB_TYPE_P(key, T_SYMBOL)) {
|
|
1050
|
+
key = rb_sym2str(key);
|
|
1051
|
+
} else if (!RB_TYPE_P(key, T_STRING)) {
|
|
1052
|
+
ctx->skipped++;
|
|
1053
|
+
return ST_CONTINUE;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
key = utf8_string(key);
|
|
1057
|
+
prepared_metastruct_entry *entry =
|
|
1058
|
+
append_prepared_metastruct_entry(ctx->prepared);
|
|
1059
|
+
entry->key_len = (size_t)RSTRING_LEN(key);
|
|
1060
|
+
entry->key = copy_structured_value_bytes(
|
|
1061
|
+
&entry->value, key, entry->key_len);
|
|
1062
|
+
append_structured_value(value, 0, &entry->value);
|
|
1063
|
+
|
|
1064
|
+
return ST_CONTINUE;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
typedef struct {
|
|
1068
|
+
VALUE span;
|
|
1069
|
+
prepared_metastruct *prepared;
|
|
1070
|
+
} prepare_metastruct_call;
|
|
1071
|
+
|
|
1072
|
+
static VALUE prepare_metastruct_body(VALUE arg) {
|
|
1073
|
+
prepare_metastruct_call *call = (prepare_metastruct_call *)arg;
|
|
1074
|
+
VALUE metastruct = rb_ivar_get(call->span, at_metastruct_id);
|
|
1075
|
+
if (metastruct == Qnil) return Qnil;
|
|
1076
|
+
|
|
1077
|
+
VALUE values = rb_funcall(metastruct, id_to_h, 0);
|
|
1078
|
+
Check_Type(values, T_HASH);
|
|
1079
|
+
if (RHASH_SIZE(values) == 0) return Qnil;
|
|
1080
|
+
|
|
1081
|
+
metastruct_prepare_ctx ctx = {.prepared = call->prepared, .skipped = 0};
|
|
1082
|
+
rb_hash_foreach(values, prepare_metastruct_iter_cb, (VALUE)&ctx);
|
|
1083
|
+
if (ctx.skipped > 0) {
|
|
1084
|
+
log_warning(rb_sprintf(
|
|
1085
|
+
"Native trace exporter: skipped %ld meta_struct entries with non-string keys",
|
|
1086
|
+
ctx.skipped));
|
|
1087
|
+
}
|
|
1088
|
+
return Qnil;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/* Prepare stable token storage before allocating the Rust span. Any Ruby
|
|
1092
|
+
* callback or non-local exit is contained here, where deterministic cleanup
|
|
1093
|
+
* does not need to account for Rust span ownership. */
|
|
1094
|
+
static void prepare_metastruct(VALUE span, prepared_metastruct *prepared) {
|
|
1095
|
+
prepare_metastruct_call call = {.span = span, .prepared = prepared};
|
|
1096
|
+
int state = 0;
|
|
1097
|
+
rb_protect(prepare_metastruct_body, (VALUE)&call, &state);
|
|
1098
|
+
if (state) {
|
|
1099
|
+
free_prepared_metastruct(prepared);
|
|
1100
|
+
rb_jump_tag(state);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
static void set_prepared_metastruct(
|
|
1105
|
+
ddog_TracerSpan *span, prepared_metastruct *prepared) {
|
|
1106
|
+
for (size_t i = 0; i < prepared->len; i++) {
|
|
1107
|
+
prepared_metastruct_entry *entry = &prepared->entries[i];
|
|
1108
|
+
ddog_Slice_TracerValueToken tokens = {
|
|
1109
|
+
.ptr = entry->value.tokens,
|
|
1110
|
+
.len = entry->value.len,
|
|
1111
|
+
};
|
|
1112
|
+
ddog_CharSlice key = {
|
|
1113
|
+
.ptr = (const char *)entry->key,
|
|
1114
|
+
.len = entry->key_len,
|
|
1115
|
+
};
|
|
1116
|
+
ddog_TraceExporterError *err =
|
|
1117
|
+
ddog_tracer_span_set_meta_struct(span, key, tokens);
|
|
1118
|
+
if (err != NULL) {
|
|
1119
|
+
free_prepared_metastruct(prepared);
|
|
1120
|
+
check_exporter_error("Failed to set span meta_struct", err);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
free_prepared_metastruct(prepared);
|
|
1124
|
+
}
|
|
1125
|
+
/* ========================================================================
|
|
1126
|
+
* Internal: convert a Ruby Span into a raw_span_owner
|
|
1127
|
+
*
|
|
1128
|
+
* The caller keeps its ensure handler active until the span is either wrapped
|
|
1129
|
+
* in TypedData or consumed by a trace chunk.
|
|
1130
|
+
* ======================================================================== */
|
|
1131
|
+
|
|
1132
|
+
/* rb_ensure body for span conversion. Event resources are owned by the inner
|
|
1133
|
+
* ensure, while the raw span is owned by the caller's outer ensure. */
|
|
1134
|
+
static VALUE build_rust_span(VALUE arg) {
|
|
1135
|
+
span_conversion_ctx *conversion = (span_conversion_ctx *)arg;
|
|
1136
|
+
VALUE span = conversion->span;
|
|
1137
|
+
|
|
1138
|
+
if ((size_t)conversion->event_count > SIZE_MAX / sizeof(ddog_TracerSpanEvent *)) {
|
|
1139
|
+
rb_raise(rb_eNoMemError, "span event conversion allocation is too large");
|
|
1140
|
+
}
|
|
1141
|
+
size_t event_pointers_size = (size_t)conversion->event_count * sizeof(ddog_TracerSpanEvent *);
|
|
1142
|
+
size_t scratch_alignment = offsetof(span_event_array_scratch_alignment, value);
|
|
1143
|
+
if (event_pointers_size > SIZE_MAX - (scratch_alignment - 1)) {
|
|
1144
|
+
rb_raise(rb_eNoMemError, "span event conversion allocation is too large");
|
|
1145
|
+
}
|
|
1146
|
+
size_t scratch_offset = event_pointers_size == 0
|
|
1147
|
+
? 0
|
|
1148
|
+
: ((event_pointers_size + scratch_alignment - 1) / scratch_alignment) * scratch_alignment;
|
|
1149
|
+
if (conversion->max_array_length > (SIZE_MAX - scratch_offset) / sizeof(span_event_array_scratch)) {
|
|
1150
|
+
rb_raise(rb_eNoMemError, "span event conversion allocation is too large");
|
|
1151
|
+
}
|
|
1152
|
+
/* One allocation means no second Ruby allocation can non-locally exit and
|
|
1153
|
+
* strand the first. rb_ensure owns it from the moment this call returns. */
|
|
1154
|
+
size_t allocation_size = scratch_offset + conversion->max_array_length * sizeof(span_event_array_scratch);
|
|
1155
|
+
if (allocation_size > 0) {
|
|
1156
|
+
conversion->allocation = ruby_xcalloc(1, allocation_size);
|
|
1157
|
+
conversion->events = (ddog_TracerSpanEvent **)conversion->allocation;
|
|
1158
|
+
conversion->array_scratch = (char *)conversion->allocation + scratch_offset;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
build_native_events(conversion);
|
|
1162
|
+
/* Read Ruby ivars */
|
|
1163
|
+
VALUE rb_name = rb_ivar_get(span, at_name_id);
|
|
1164
|
+
VALUE rb_service = rb_ivar_get(span, at_service_id);
|
|
1165
|
+
VALUE rb_resource = rb_ivar_get(span, at_resource_id);
|
|
1166
|
+
VALUE rb_type = rb_ivar_get(span, at_type_id);
|
|
1167
|
+
VALUE rb_span_id = rb_ivar_get(span, at_id_id);
|
|
1168
|
+
VALUE rb_parent_id = rb_ivar_get(span, at_parent_id_id);
|
|
1169
|
+
VALUE rb_trace_id = rb_ivar_get(span, at_trace_id_id);
|
|
1170
|
+
VALUE rb_status = rb_ivar_get(span, at_status_id);
|
|
1171
|
+
|
|
1172
|
+
/* Validate scalar strings without borrowing their pointers. Link and
|
|
1173
|
+
* meta_struct normalization below can call arbitrary Ruby code that mutates
|
|
1174
|
+
* these strings and invalidates any prior RSTRING_PTR. */
|
|
1175
|
+
ENFORCE_TYPE(rb_name, T_STRING);
|
|
1176
|
+
if (rb_service != Qnil) ENFORCE_TYPE(rb_service, T_STRING);
|
|
1177
|
+
if (rb_resource != Qnil) ENFORCE_TYPE(rb_resource, T_STRING);
|
|
1178
|
+
if (rb_type != Qnil) ENFORCE_TYPE(rb_type, T_STRING);
|
|
1179
|
+
|
|
1180
|
+
/* Convert scalars that may call Ruby. */
|
|
1181
|
+
uint64_t span_id = NUM2ULL(rb_span_id);
|
|
1182
|
+
uint64_t parent_id = NUM2ULL(rb_parent_id);
|
|
1183
|
+
int32_t error_val = NUM2INT(rb_status);
|
|
1184
|
+
|
|
1185
|
+
trace_id_t trace_id = split_trace_id(rb_trace_id);
|
|
1186
|
+
|
|
1187
|
+
/* start (ns) */
|
|
1188
|
+
int64_t start_ns = 0;
|
|
1189
|
+
VALUE rb_start_time = rb_ivar_get(span, at_start_time_id);
|
|
1190
|
+
if (rb_start_time != Qnil) {
|
|
1191
|
+
start_ns = time_to_nanos(rb_start_time);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/* duration (ns) */
|
|
1195
|
+
int64_t duration_ns = 0;
|
|
1196
|
+
VALUE rb_duration_ivar = rb_ivar_get(span, at_duration_id);
|
|
1197
|
+
if (rb_duration_ivar != Qnil) {
|
|
1198
|
+
duration_ns = (int64_t)(NUM2DBL(rb_duration_ivar) * 1e9);
|
|
1199
|
+
} else {
|
|
1200
|
+
VALUE dur = rb_funcall(span, id_duration_method, 0);
|
|
1201
|
+
if (dur != Qnil) duration_ns = (int64_t)(NUM2DBL(dur) * 1e9);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/* Structured-value and link normalization can call Ruby code. Prepare both
|
|
1205
|
+
* before borrowing scalar string pointers or allocating the Rust span. */
|
|
1206
|
+
prepared_metastruct metastruct = {0};
|
|
1207
|
+
prepare_metastruct(span, &metastruct);
|
|
1208
|
+
|
|
1209
|
+
/* Snapshot canonical links and all string bytes before allocating Rust
|
|
1210
|
+
* state. rb_protect guarantees partial C-owned snapshots are reclaimed if a
|
|
1211
|
+
* default proc, to_hash, validation, or allocation raises. */
|
|
1212
|
+
VALUE rb_links = rb_ivar_get(span, at_links_id);
|
|
1213
|
+
if (RB_UNLIKELY(!RB_TYPE_P(rb_links, T_ARRAY))) {
|
|
1214
|
+
/* Read @links after prepare_metastruct so a meta_struct callback that
|
|
1215
|
+
* reassigns it is honoured. That ordering means this raise happens with
|
|
1216
|
+
* C-owned metastruct storage already allocated, which the caller's
|
|
1217
|
+
* free_raw_span ensure handler does not reclaim. */
|
|
1218
|
+
free_prepared_metastruct(&metastruct);
|
|
1219
|
+
ENFORCE_TYPE(rb_links, T_ARRAY);
|
|
1220
|
+
}
|
|
1221
|
+
span_links_snapshot links_snapshot = {
|
|
1222
|
+
.rb_links = rb_links,
|
|
1223
|
+
};
|
|
1224
|
+
if (RARRAY_LEN(rb_links) > 0) {
|
|
1225
|
+
int snapshot_state = 0;
|
|
1226
|
+
rb_protect(prepare_span_links_snapshot, (VALUE)&links_snapshot, &snapshot_state);
|
|
1227
|
+
if (snapshot_state) {
|
|
1228
|
+
free_span_links_snapshot(&links_snapshot);
|
|
1229
|
+
free_prepared_metastruct(&metastruct);
|
|
1230
|
+
rb_jump_tag(snapshot_state);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
/* No Ruby callbacks occur between borrowing these pointers and the FFI call. */
|
|
1235
|
+
ddog_CharSlice name_s = char_slice_from_ruby_string(rb_name);
|
|
1236
|
+
ddog_CharSlice service_s = nullable_char_slice(rb_service);
|
|
1237
|
+
ddog_CharSlice resource_s = nullable_char_slice(rb_resource);
|
|
1238
|
+
ddog_CharSlice type_s = nullable_char_slice(rb_type);
|
|
1239
|
+
|
|
1240
|
+
/* Create Rust span and immediately consume the stable prepared values. */
|
|
1241
|
+
ddog_TracerSpanFields fields = {
|
|
1242
|
+
.service = service_s,
|
|
1243
|
+
.name = name_s,
|
|
1244
|
+
.resource = resource_s,
|
|
1245
|
+
.span_type = type_s,
|
|
1246
|
+
.trace_id_low = trace_id.low,
|
|
1247
|
+
.trace_id_high = trace_id.high,
|
|
1248
|
+
.span_id = span_id,
|
|
1249
|
+
.parent_id = parent_id,
|
|
1250
|
+
.start = start_ns,
|
|
1251
|
+
.duration = duration_ns,
|
|
1252
|
+
.error = error_val,
|
|
1253
|
+
};
|
|
1254
|
+
|
|
1255
|
+
ddog_TraceExporterError *err = ddog_tracer_span_new(&conversion->owner->span, &fields);
|
|
1256
|
+
if (err != NULL) {
|
|
1257
|
+
free_span_links_snapshot(&links_snapshot);
|
|
1258
|
+
free_prepared_metastruct(&metastruct);
|
|
1259
|
+
}
|
|
1260
|
+
check_exporter_error("Failed to create TracerSpan", err);
|
|
1261
|
+
|
|
1262
|
+
if (links_snapshot.link_count > 0) {
|
|
1263
|
+
ddog_Slice_TracerSpanLink links_slice = {
|
|
1264
|
+
.ptr = links_snapshot.ffi_links,
|
|
1265
|
+
.len = links_snapshot.link_count,
|
|
1266
|
+
};
|
|
1267
|
+
/* libdatadog validates link strings as UTF-8, matching the native meta
|
|
1268
|
+
* setters. A validation error rejects this span conversion and therefore the
|
|
1269
|
+
* complete batch; send_traces reports it as an InternalErrorResponse. */
|
|
1270
|
+
err = ddog_tracer_span_set_links(conversion->owner->span, links_slice);
|
|
1271
|
+
free_span_links_snapshot(&links_snapshot);
|
|
1272
|
+
if (err != NULL) free_prepared_metastruct(&metastruct);
|
|
1273
|
+
check_exporter_error("Failed to set span links", err);
|
|
1274
|
+
}
|
|
1275
|
+
set_prepared_metastruct(conversion->owner->span, &metastruct);
|
|
1276
|
+
|
|
1277
|
+
for (long i = 0; i < conversion->event_count; i++) {
|
|
1278
|
+
err = ddog_tracer_span_add_event(conversion->owner->span, conversion->events[i]);
|
|
1279
|
+
conversion->events[i] = NULL; /* add_event consumes the event on every path. */
|
|
1280
|
+
check_exporter_error("Failed to attach span event", err);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
hash_iter_ctx ctx = {.span = conversion->owner->span, .error = NULL, .skipped = 0};
|
|
1284
|
+
|
|
1285
|
+
VALUE rb_meta = rb_ivar_get(span, at_meta_id);
|
|
1286
|
+
if (RB_TYPE_P(rb_meta, T_HASH) && RHASH_SIZE(rb_meta) > 0) {
|
|
1287
|
+
rb_hash_foreach(rb_meta, meta_iter_cb, (VALUE)&ctx);
|
|
1288
|
+
check_exporter_error("Failed to set span meta", ctx.error);
|
|
1289
|
+
if (ctx.skipped > 0) {
|
|
1290
|
+
log_warning(rb_sprintf(
|
|
1291
|
+
"Native trace exporter: skipped %ld non-string meta entries",
|
|
1292
|
+
ctx.skipped));
|
|
1293
|
+
ctx.skipped = 0;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
VALUE rb_metrics = rb_ivar_get(span, at_metrics_id);
|
|
1298
|
+
if (RB_TYPE_P(rb_metrics, T_HASH) && RHASH_SIZE(rb_metrics) > 0) {
|
|
1299
|
+
rb_hash_foreach(rb_metrics, metrics_iter_cb, (VALUE)&ctx);
|
|
1300
|
+
check_exporter_error("Failed to set span metric", ctx.error);
|
|
1301
|
+
if (ctx.skipped > 0) {
|
|
1302
|
+
log_warning(rb_sprintf(
|
|
1303
|
+
"Native trace exporter: skipped %ld non-numeric metrics entries",
|
|
1304
|
+
ctx.skipped));
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
return Qnil;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
static void convert_ruby_span_to_rust(VALUE span, VALUE native_events_supported, raw_span_owner *owner) {
|
|
1312
|
+
span_conversion_ctx ctx = {
|
|
1313
|
+
.span = span,
|
|
1314
|
+
.normalized_events = Qnil,
|
|
1315
|
+
.owner = owner,
|
|
1316
|
+
};
|
|
1317
|
+
if (native_events_supported == Qtrue) {
|
|
1318
|
+
ctx.normalized_events = normalize_span_events(span, &ctx.max_array_length);
|
|
1319
|
+
ctx.event_count = RARRAY_LEN(ctx.normalized_events);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
rb_ensure(
|
|
1323
|
+
build_rust_span, (VALUE)&ctx,
|
|
1324
|
+
free_span_conversion, (VALUE)&ctx);
|
|
1325
|
+
RB_GC_GUARD(ctx.normalized_events);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
static VALUE free_raw_span(VALUE arg) {
|
|
1329
|
+
raw_span_owner *owner = (raw_span_owner *)arg;
|
|
1330
|
+
if (owner->span != NULL) {
|
|
1331
|
+
ddog_tracer_span_free(owner->span);
|
|
1332
|
+
owner->span = NULL;
|
|
1333
|
+
}
|
|
1334
|
+
return Qnil;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/* ========================================================================
|
|
1338
|
+
* TracerSpan._native_from_span
|
|
1339
|
+
* ======================================================================== */
|
|
1340
|
+
|
|
1341
|
+
typedef struct {
|
|
1342
|
+
VALUE span;
|
|
1343
|
+
raw_span_owner owner;
|
|
1344
|
+
} wrap_span_ctx;
|
|
1345
|
+
|
|
1346
|
+
static VALUE convert_and_wrap_span(VALUE arg) {
|
|
1347
|
+
wrap_span_ctx *ctx = (wrap_span_ctx *)arg;
|
|
1348
|
+
convert_ruby_span_to_rust(ctx->span, Qtrue, &ctx->owner);
|
|
1349
|
+
|
|
1350
|
+
VALUE wrapped = TypedData_Wrap_Struct(
|
|
1351
|
+
tracer_span_class, &tracer_span_typed_data, ctx->owner.span);
|
|
1352
|
+
ctx->owner.span = NULL;
|
|
1353
|
+
return wrapped;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
static VALUE _native_from_span(DDTRACE_UNUSED VALUE klass, VALUE span) {
|
|
1357
|
+
wrap_span_ctx ctx = {.span = span, .owner = {.span = NULL}};
|
|
1358
|
+
return rb_ensure(
|
|
1359
|
+
convert_and_wrap_span, (VALUE)&ctx,
|
|
1360
|
+
free_raw_span, (VALUE)&ctx.owner);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
/* ========================================================================
|
|
1364
|
+
* Response class helpers
|
|
1365
|
+
* ======================================================================== */
|
|
1366
|
+
|
|
1367
|
+
/*
|
|
1368
|
+
* Build an error response, classifying the error code into the
|
|
1369
|
+
* Transport::Response categories:
|
|
1370
|
+
*
|
|
1371
|
+
* HTTP_CLIENT -> client_error? (4xx family)
|
|
1372
|
+
* HTTP_SERVER -> server_error? (5xx family)
|
|
1373
|
+
* everything else -> internal_error?
|
|
1374
|
+
*/
|
|
1375
|
+
static VALUE create_error_response(ddog_TraceExporterErrorCode code,
|
|
1376
|
+
long trace_count) {
|
|
1377
|
+
VALUE kwargs = rb_hash_new();
|
|
1378
|
+
rb_hash_aset(kwargs, ID2SYM(kw_ok), Qfalse);
|
|
1379
|
+
rb_hash_aset(kwargs, ID2SYM(kw_internal_error), (code != DDOG_TRACE_EXPORTER_ERROR_CODE_HTTP_CLIENT &&
|
|
1380
|
+
code != DDOG_TRACE_EXPORTER_ERROR_CODE_HTTP_SERVER) ? Qtrue : Qfalse);
|
|
1381
|
+
rb_hash_aset(kwargs, ID2SYM(kw_server_error), code == DDOG_TRACE_EXPORTER_ERROR_CODE_HTTP_SERVER ? Qtrue : Qfalse);
|
|
1382
|
+
rb_hash_aset(kwargs, ID2SYM(kw_client_error), code == DDOG_TRACE_EXPORTER_ERROR_CODE_HTTP_CLIENT ? Qtrue : Qfalse);
|
|
1383
|
+
rb_hash_aset(kwargs, ID2SYM(kw_trace_count), LONG2NUM(trace_count));
|
|
1384
|
+
return rb_funcallv_kw(response_class, id_new, 1, &kwargs, RB_PASS_KEYWORDS);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
/*
|
|
1388
|
+
* Build a success response, optionally carrying the agent's response body
|
|
1389
|
+
* as +payload+.
|
|
1390
|
+
*
|
|
1391
|
+
* +payload+ is the raw HTTP response body returned by the Datadog Agent
|
|
1392
|
+
* (typically JSON containing +rate_by_service+). It is surfaced here so
|
|
1393
|
+
* that callers matching the +Datadog::Core::Transport::Response+ interface
|
|
1394
|
+
* can parse service sampling rates, just as the Net::HTTP transport does.
|
|
1395
|
+
*/
|
|
1396
|
+
static VALUE create_ok_response(long trace_count, VALUE payload) {
|
|
1397
|
+
VALUE kwargs = rb_hash_new();
|
|
1398
|
+
rb_hash_aset(kwargs, ID2SYM(kw_ok), Qtrue);
|
|
1399
|
+
rb_hash_aset(kwargs, ID2SYM(kw_trace_count), LONG2NUM(trace_count));
|
|
1400
|
+
rb_hash_aset(kwargs, ID2SYM(kw_payload), payload);
|
|
1401
|
+
return rb_funcallv_kw(response_class, id_new, 1, &kwargs, RB_PASS_KEYWORDS);
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/* ========================================================================
|
|
1405
|
+
* TraceExporter._native_new
|
|
1406
|
+
*
|
|
1407
|
+
* Creates a Rust TraceExporter with the given configuration.
|
|
1408
|
+
*
|
|
1409
|
+
* Ruby signature:
|
|
1410
|
+
* TraceExporter._native_new(
|
|
1411
|
+
* url:, tracer_version: nil, language: nil, language_version: nil,
|
|
1412
|
+
* language_interpreter: nil, hostname: nil, env: nil,
|
|
1413
|
+
* service: nil, version: nil) -> TraceExporter
|
|
1414
|
+
*
|
|
1415
|
+
* +url+ is required (String). All other arguments may be nil.
|
|
1416
|
+
* ======================================================================== */
|
|
1417
|
+
|
|
1418
|
+
static VALUE _native_exporter_new(
|
|
1419
|
+
int argc, VALUE *argv, DDTRACE_UNUSED VALUE klass
|
|
1420
|
+
) {
|
|
1421
|
+
VALUE options;
|
|
1422
|
+
rb_scan_args(argc, argv, "0:", &options);
|
|
1423
|
+
if (options == Qnil) options = rb_hash_new();
|
|
1424
|
+
|
|
1425
|
+
VALUE rb_url = rb_hash_fetch(options, ID2SYM(rb_intern("url")));
|
|
1426
|
+
VALUE rb_tracer_version = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_version")));
|
|
1427
|
+
VALUE rb_language = rb_hash_fetch(options, ID2SYM(rb_intern("language")));
|
|
1428
|
+
VALUE rb_language_version = rb_hash_fetch(options, ID2SYM(rb_intern("language_version")));
|
|
1429
|
+
VALUE rb_language_interpreter = rb_hash_fetch(options, ID2SYM(rb_intern("language_interpreter")));
|
|
1430
|
+
VALUE rb_hostname = rb_hash_fetch(options, ID2SYM(rb_intern("hostname")));
|
|
1431
|
+
VALUE rb_env = rb_hash_fetch(options, ID2SYM(rb_intern("env")));
|
|
1432
|
+
VALUE rb_service = rb_hash_fetch(options, ID2SYM(rb_intern("service")));
|
|
1433
|
+
VALUE rb_version = rb_hash_fetch(options, ID2SYM(rb_intern("version")));
|
|
1434
|
+
|
|
1435
|
+
/* Phase 1: validate types (may raise, no Rust resources yet) */
|
|
1436
|
+
ENFORCE_TYPE(rb_url, T_STRING);
|
|
1437
|
+
if (rb_tracer_version != Qnil) ENFORCE_TYPE(rb_tracer_version, T_STRING);
|
|
1438
|
+
if (rb_language != Qnil) ENFORCE_TYPE(rb_language, T_STRING);
|
|
1439
|
+
if (rb_language_version != Qnil) ENFORCE_TYPE(rb_language_version, T_STRING);
|
|
1440
|
+
if (rb_language_interpreter != Qnil) ENFORCE_TYPE(rb_language_interpreter, T_STRING);
|
|
1441
|
+
if (rb_hostname != Qnil) ENFORCE_TYPE(rb_hostname, T_STRING);
|
|
1442
|
+
if (rb_env != Qnil) ENFORCE_TYPE(rb_env, T_STRING);
|
|
1443
|
+
if (rb_service != Qnil) ENFORCE_TYPE(rb_service, T_STRING);
|
|
1444
|
+
if (rb_version != Qnil) ENFORCE_TYPE(rb_version, T_STRING);
|
|
1445
|
+
|
|
1446
|
+
/* Phase 2: configure before creating the separately-owned runtime. */
|
|
1447
|
+
ddog_TraceExporterConfig *config = NULL;
|
|
1448
|
+
ddog_trace_exporter_config_new(&config);
|
|
1449
|
+
|
|
1450
|
+
set_config_field(config, ddog_trace_exporter_config_set_url, rb_url, "url");
|
|
1451
|
+
set_config_field(config, ddog_trace_exporter_config_set_tracer_version, rb_tracer_version, "tracer_version");
|
|
1452
|
+
set_config_field(config, ddog_trace_exporter_config_set_language, rb_language, "language");
|
|
1453
|
+
set_config_field(config, ddog_trace_exporter_config_set_lang_version, rb_language_version, "language_version");
|
|
1454
|
+
set_config_field(config, ddog_trace_exporter_config_set_lang_interpreter, rb_language_interpreter, "language_interpreter");
|
|
1455
|
+
set_config_field(config, ddog_trace_exporter_config_set_hostname, rb_hostname, "hostname");
|
|
1456
|
+
set_config_field(config, ddog_trace_exporter_config_set_env, rb_env, "env");
|
|
1457
|
+
set_config_field(config, ddog_trace_exporter_config_set_service, rb_service, "service");
|
|
1458
|
+
set_config_field(config, ddog_trace_exporter_config_set_version, rb_version, "version");
|
|
1459
|
+
|
|
1460
|
+
/*
|
|
1461
|
+
* Create a SharedRuntime and attach it to the config before building the
|
|
1462
|
+
* exporter. The exporter holds a clone of the runtime's Arc; we keep our
|
|
1463
|
+
* own handle in the wrapper to drive fork-safety hooks and to free it when
|
|
1464
|
+
* the exporter is collected.
|
|
1465
|
+
*/
|
|
1466
|
+
const ddog_ForkSafeRuntime *runtime = NULL;
|
|
1467
|
+
ddog_SharedRuntimeFFIError *rt_err = ddog_shared_runtime_new(&runtime);
|
|
1468
|
+
if (rt_err != NULL) {
|
|
1469
|
+
ddog_trace_exporter_config_free(config);
|
|
1470
|
+
check_shared_runtime_error("Failed to create SharedRuntime", rt_err);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/*
|
|
1474
|
+
* Const asymmetry: ddog_shared_runtime_new yields a `const ddog_ForkSafeRuntime *`
|
|
1475
|
+
* but the setter takes a non-const pointer. The setter only clones the Arc,
|
|
1476
|
+
* so casting away const here is safe.
|
|
1477
|
+
*/
|
|
1478
|
+
{
|
|
1479
|
+
ddog_TraceExporterError *attach_err = ddog_trace_exporter_config_set_shared_runtime(
|
|
1480
|
+
config, (ddog_ForkSafeRuntime *)runtime);
|
|
1481
|
+
if (attach_err != NULL) {
|
|
1482
|
+
ddog_trace_exporter_config_free(config);
|
|
1483
|
+
ddog_shared_runtime_free(runtime);
|
|
1484
|
+
check_exporter_error("Failed to attach SharedRuntime to config", attach_err);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
/* Phase 3: build the exporter from the config */
|
|
1489
|
+
ddog_TraceExporter *exporter = NULL;
|
|
1490
|
+
ddog_TraceExporterError *err = ddog_trace_exporter_new(&exporter, config);
|
|
1491
|
+
ddog_trace_exporter_config_free(config);
|
|
1492
|
+
config = NULL;
|
|
1493
|
+
|
|
1494
|
+
if (err) {
|
|
1495
|
+
ddog_shared_runtime_free(runtime);
|
|
1496
|
+
check_exporter_error("Failed to create TraceExporter", err);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
trace_exporter_t *wrapper = ruby_xmalloc(sizeof(trace_exporter_t));
|
|
1500
|
+
wrapper->exporter = exporter;
|
|
1501
|
+
wrapper->runtime = runtime;
|
|
1502
|
+
|
|
1503
|
+
return TypedData_Wrap_Struct(trace_exporter_class, &trace_exporter_typed_data,
|
|
1504
|
+
wrapper);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
/* ========================================================================
|
|
1508
|
+
* Fork safety hooks
|
|
1509
|
+
*
|
|
1510
|
+
* These coordinate the tokio runtime lifecycle around process forks
|
|
1511
|
+
* (Puma, Unicorn, Passenger).
|
|
1512
|
+
* ======================================================================== */
|
|
1513
|
+
|
|
1514
|
+
static VALUE _native_before_fork(VALUE self) {
|
|
1515
|
+
trace_exporter_t *wrapper;
|
|
1516
|
+
TypedData_Get_Struct(self, trace_exporter_t, &trace_exporter_typed_data, wrapper);
|
|
1517
|
+
if (wrapper == NULL || wrapper->runtime == NULL) {
|
|
1518
|
+
raise_error(rb_eRuntimeError, "TraceExporter has not been initialized or was already freed");
|
|
1519
|
+
}
|
|
1520
|
+
ddog_SharedRuntimeFFIError *err = ddog_shared_runtime_before_fork(wrapper->runtime);
|
|
1521
|
+
check_shared_runtime_error("Failed to prepare for fork", err);
|
|
1522
|
+
return Qnil;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
static VALUE _native_after_fork_in_parent(VALUE self) {
|
|
1526
|
+
trace_exporter_t *wrapper;
|
|
1527
|
+
TypedData_Get_Struct(self, trace_exporter_t, &trace_exporter_typed_data, wrapper);
|
|
1528
|
+
if (wrapper == NULL || wrapper->runtime == NULL) {
|
|
1529
|
+
raise_error(rb_eRuntimeError, "TraceExporter has not been initialized or was already freed");
|
|
1530
|
+
}
|
|
1531
|
+
ddog_SharedRuntimeFFIError *err = ddog_shared_runtime_after_fork_parent(wrapper->runtime);
|
|
1532
|
+
check_shared_runtime_error("Failed to restore after fork in parent", err);
|
|
1533
|
+
return Qnil;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
static VALUE _native_after_fork_in_child(VALUE self) {
|
|
1537
|
+
trace_exporter_t *wrapper;
|
|
1538
|
+
TypedData_Get_Struct(self, trace_exporter_t, &trace_exporter_typed_data, wrapper);
|
|
1539
|
+
if (wrapper == NULL || wrapper->runtime == NULL) {
|
|
1540
|
+
raise_error(rb_eRuntimeError, "TraceExporter has not been initialized or was already freed");
|
|
1541
|
+
}
|
|
1542
|
+
ddog_SharedRuntimeFFIError *err = ddog_shared_runtime_after_fork_child(wrapper->runtime);
|
|
1543
|
+
check_shared_runtime_error("Failed to restore after fork in child", err);
|
|
1544
|
+
return Qnil;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
/* ========================================================================
|
|
1548
|
+
* GVL-release helper for ddog_trace_exporter_send_trace_chunks
|
|
1549
|
+
*
|
|
1550
|
+
* The send call performs blocking network I/O. Releasing the GVL lets
|
|
1551
|
+
* other Ruby threads (application code, test mock servers, etc.) run
|
|
1552
|
+
* while we wait for the agent's response.
|
|
1553
|
+
* ======================================================================== */
|
|
1554
|
+
|
|
1555
|
+
typedef struct {
|
|
1556
|
+
const ddog_TraceExporter *exporter;
|
|
1557
|
+
ddog_TracerTraceChunks *chunks;
|
|
1558
|
+
ddog_TraceExporterResponse *response;
|
|
1559
|
+
ddog_TraceExporterCancelToken *cancel_token; /* borrowed, not owned */
|
|
1560
|
+
ddog_TraceExporterErrorCode error_code;
|
|
1561
|
+
bool failed;
|
|
1562
|
+
bool send_ran;
|
|
1563
|
+
} send_chunks_args_t;
|
|
1564
|
+
|
|
1565
|
+
static void *send_chunks_without_gvl(void *data) {
|
|
1566
|
+
send_chunks_args_t *args = (send_chunks_args_t *)data;
|
|
1567
|
+
ddog_TraceExporterError *err = ddog_trace_exporter_send_trace_chunks(
|
|
1568
|
+
args->exporter, args->chunks, &args->response, args->cancel_token);
|
|
1569
|
+
if (err != NULL) {
|
|
1570
|
+
args->error_code = err->code;
|
|
1571
|
+
args->failed = true;
|
|
1572
|
+
ddog_trace_exporter_error_free(err);
|
|
1573
|
+
}
|
|
1574
|
+
args->send_ran = true;
|
|
1575
|
+
return NULL;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
/*
|
|
1579
|
+
* Unblock function: cooperatively cancel an in-flight send.
|
|
1580
|
+
*
|
|
1581
|
+
* Called by Ruby when an interrupt (Thread#kill, shutdown) fires while
|
|
1582
|
+
* the thread is inside rb_thread_call_without_gvl2. Cancelling the
|
|
1583
|
+
* token causes the Rust HTTP pipeline to abort the in-flight request
|
|
1584
|
+
* and return promptly, which is not possible with RUBY_UBF_IO's
|
|
1585
|
+
* signal-based approach.
|
|
1586
|
+
*/
|
|
1587
|
+
static void interrupt_exporter_call(void *cancel_token) {
|
|
1588
|
+
ddog_trace_exporter_cancel_token_cancel(
|
|
1589
|
+
(const ddog_TraceExporterCancelToken *)cancel_token);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/*
|
|
1593
|
+
* Check for a pending Ruby exception without raising it.
|
|
1594
|
+
* Mirrors the profiling extension's check_if_pending_exception().
|
|
1595
|
+
*/
|
|
1596
|
+
static VALUE process_pending_interruptions(DDTRACE_UNUSED VALUE _) {
|
|
1597
|
+
rb_thread_check_ints();
|
|
1598
|
+
return Qnil;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
__attribute__((warn_unused_result))
|
|
1602
|
+
static int check_if_pending_exception(void) {
|
|
1603
|
+
int pending_exception;
|
|
1604
|
+
rb_protect(process_pending_interruptions, Qnil, &pending_exception);
|
|
1605
|
+
return pending_exception;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
/* ========================================================================
|
|
1609
|
+
* TraceExporter#_native_send_traces
|
|
1610
|
+
*
|
|
1611
|
+
* Ruby signature:
|
|
1612
|
+
* exporter._native_send_traces(traces, native_events_supported) -> Array[Response]
|
|
1613
|
+
*
|
|
1614
|
+
* +traces+ is an Array of Arrays of Spans:
|
|
1615
|
+
* [[span, span, ...], [span, ...], ...]
|
|
1616
|
+
*
|
|
1617
|
+
* Each inner array maps to one trace chunk (Vec<Span> in Rust).
|
|
1618
|
+
*
|
|
1619
|
+
* On success returns [Response(ok: true, trace_count: N)].
|
|
1620
|
+
* On error returns [Response(ok: false, ...)].
|
|
1621
|
+
*
|
|
1622
|
+
* The chunk-building loop calls into Ruby (ENFORCE_TYPE,
|
|
1623
|
+
* convert_ruby_span_to_rust) which may raise. We use rb_ensure so
|
|
1624
|
+
* that the Rust-allocated chunks are freed if an exception fires
|
|
1625
|
+
* before the send consumes them.
|
|
1626
|
+
* ======================================================================== */
|
|
1627
|
+
|
|
1628
|
+
/* Context shared between the body and ensure callbacks. */
|
|
1629
|
+
typedef struct {
|
|
1630
|
+
const ddog_TraceExporter *exporter;
|
|
1631
|
+
VALUE traces;
|
|
1632
|
+
VALUE native_events_supported;
|
|
1633
|
+
long trace_count;
|
|
1634
|
+
raw_span_owner span_owner;
|
|
1635
|
+
ddog_TracerTraceChunks *chunks; /* NULL after send consumes it */
|
|
1636
|
+
} send_traces_ctx;
|
|
1637
|
+
|
|
1638
|
+
/*
|
|
1639
|
+
* Body: build trace chunks from Ruby spans, then send them.
|
|
1640
|
+
* Passed to rb_ensure as the "try" block.
|
|
1641
|
+
*/
|
|
1642
|
+
static VALUE build_and_send_traces(VALUE arg) {
|
|
1643
|
+
send_traces_ctx *ctx = (send_traces_ctx *)arg;
|
|
1644
|
+
|
|
1645
|
+
for (long i = 0; i < ctx->trace_count; i++) {
|
|
1646
|
+
VALUE chunk_spans = rb_ary_entry(ctx->traces, i);
|
|
1647
|
+
ENFORCE_TYPE(chunk_spans, T_ARRAY);
|
|
1648
|
+
|
|
1649
|
+
long span_count = RARRAY_LEN(chunk_spans);
|
|
1650
|
+
/* Propagate a begin_chunk failure instead of swallowing it: continuing
|
|
1651
|
+
* would build an incomplete payload and still report success. rb_ensure
|
|
1652
|
+
* frees chunks on the raise. Today this only fails for an absurd
|
|
1653
|
+
* span_count, but a future libdatadog change (e.g. a fallible allocator)
|
|
1654
|
+
* could make it reachable. */
|
|
1655
|
+
ddog_TraceExporterError *begin_err =
|
|
1656
|
+
ddog_tracer_trace_chunks_begin_chunk(ctx->chunks, (size_t)span_count);
|
|
1657
|
+
check_exporter_error("Failed to begin trace chunk", begin_err);
|
|
1658
|
+
for (long j = 0; j < span_count; j++) {
|
|
1659
|
+
convert_ruby_span_to_rust(
|
|
1660
|
+
rb_ary_entry(chunk_spans, j), ctx->native_events_supported, &ctx->span_owner);
|
|
1661
|
+
|
|
1662
|
+
ddog_TraceExporterError *push_err =
|
|
1663
|
+
ddog_tracer_trace_chunks_push_span(ctx->chunks, ctx->span_owner.span);
|
|
1664
|
+
/* push_span consumes the span on every path. */
|
|
1665
|
+
ctx->span_owner.span = NULL;
|
|
1666
|
+
check_exporter_error("Failed to push span into trace chunk", push_err);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
/*
|
|
1671
|
+
* Send with the GVL released so other Ruby threads run during I/O.
|
|
1672
|
+
*
|
|
1673
|
+
* Custom behaviour of this call site:
|
|
1674
|
+
* - We use the gvl2 variant precisely because it does NOT auto-raise a
|
|
1675
|
+
* pending interrupt on return: the send consumes chunks and allocates
|
|
1676
|
+
* a Rust response, so we must inspect/free those before letting any
|
|
1677
|
+
* exception propagate (otherwise they leak).
|
|
1678
|
+
* - The unblock function cancels a per-send cancellation token, which
|
|
1679
|
+
* cooperatively aborts the in-flight Rust HTTP request (RUBY_UBF_IO
|
|
1680
|
+
* could not cancel the Rust pipeline).
|
|
1681
|
+
* - An interrupt can make gvl2 return before send_chunks_without_gvl
|
|
1682
|
+
* runs, so we loop until the send actually executes or an exception
|
|
1683
|
+
* is pending.
|
|
1684
|
+
*/
|
|
1685
|
+
ddog_TraceExporterCancelToken *cancel_token =
|
|
1686
|
+
ddog_trace_exporter_cancel_token_new();
|
|
1687
|
+
|
|
1688
|
+
send_chunks_args_t args = {
|
|
1689
|
+
.exporter = ctx->exporter,
|
|
1690
|
+
.chunks = ctx->chunks,
|
|
1691
|
+
.response = NULL,
|
|
1692
|
+
.cancel_token = cancel_token,
|
|
1693
|
+
.failed = false,
|
|
1694
|
+
.send_ran = false,
|
|
1695
|
+
};
|
|
1696
|
+
|
|
1697
|
+
int pending_exception = 0;
|
|
1698
|
+
while (!args.send_ran && !pending_exception) {
|
|
1699
|
+
rb_thread_call_without_gvl2(
|
|
1700
|
+
send_chunks_without_gvl, &args,
|
|
1701
|
+
interrupt_exporter_call, cancel_token);
|
|
1702
|
+
|
|
1703
|
+
if (!args.send_ran) {
|
|
1704
|
+
pending_exception = check_if_pending_exception();
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
ddog_trace_exporter_cancel_token_drop(cancel_token);
|
|
1709
|
+
/* Only null chunks when the send actually ran and consumed them.
|
|
1710
|
+
* If an interrupt fired before the send executed, chunks are still
|
|
1711
|
+
* live and the ensure handler must free them. */
|
|
1712
|
+
if (args.send_ran) {
|
|
1713
|
+
ctx->chunks = NULL;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
/* Extract the response body as a Ruby string before freeing. */
|
|
1717
|
+
VALUE payload = Qnil;
|
|
1718
|
+
if (args.response != NULL) {
|
|
1719
|
+
ddog_ByteSlice body =
|
|
1720
|
+
ddog_trace_exporter_response_get_body(args.response);
|
|
1721
|
+
if (body.len > 0) {
|
|
1722
|
+
payload = rb_str_new((const char *)body.ptr, (long)body.len);
|
|
1723
|
+
}
|
|
1724
|
+
ddog_trace_exporter_response_free(args.response);
|
|
1725
|
+
args.response = NULL;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/*
|
|
1729
|
+
* Re-check for a pending interrupt unconditionally before deciding the
|
|
1730
|
+
* outcome. In a race, the unblock function (interrupt_exporter_call) can
|
|
1731
|
+
* fire -- cancelling the token -- while the send still completes, so
|
|
1732
|
+
* rb_thread_call_without_gvl2 returns with args.send_ran == true. In that
|
|
1733
|
+
* case the loop above exits without ever calling check_if_pending_exception(),
|
|
1734
|
+
* leaving the interrupt pending. If we did not check here, the cancelled
|
|
1735
|
+
* send would fall through and be reported as an ordinary transport error
|
|
1736
|
+
* response, swallowing the interrupt (e.g. Thread#kill / shutdown).
|
|
1737
|
+
*
|
|
1738
|
+
* This runs after the response has already been extracted and freed and
|
|
1739
|
+
* after chunks have been handed off to the ensure handler, so re-raising
|
|
1740
|
+
* here leaks nothing.
|
|
1741
|
+
*/
|
|
1742
|
+
if (!pending_exception) {
|
|
1743
|
+
pending_exception = check_if_pending_exception();
|
|
1744
|
+
}
|
|
1745
|
+
if (pending_exception) {
|
|
1746
|
+
rb_jump_tag(pending_exception);
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
if (args.failed) {
|
|
1750
|
+
VALUE err_resp = create_error_response(args.error_code, ctx->trace_count);
|
|
1751
|
+
return rb_ary_new_from_args(1, err_resp);
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
VALUE ok_resp = create_ok_response(ctx->trace_count, payload);
|
|
1755
|
+
return rb_ary_new_from_args(1, ok_resp);
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
/*
|
|
1759
|
+
* Ensure: free the current raw span and any chunks not consumed by the send.
|
|
1760
|
+
* This runs whether build_and_send_traces returned normally or raised.
|
|
1761
|
+
*/
|
|
1762
|
+
static VALUE free_send_resources(VALUE arg) {
|
|
1763
|
+
send_traces_ctx *ctx = (send_traces_ctx *)arg;
|
|
1764
|
+
free_raw_span((VALUE)&ctx->span_owner);
|
|
1765
|
+
if (ctx->chunks != NULL) {
|
|
1766
|
+
ddog_tracer_trace_chunks_free(ctx->chunks);
|
|
1767
|
+
ctx->chunks = NULL;
|
|
1768
|
+
}
|
|
1769
|
+
return Qnil;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
static VALUE _native_send_traces(VALUE self, VALUE traces, VALUE native_events_supported) {
|
|
1773
|
+
ENFORCE_TYPE(traces, T_ARRAY);
|
|
1774
|
+
if (native_events_supported != Qtrue && native_events_supported != Qfalse) {
|
|
1775
|
+
rb_raise(rb_eTypeError, "native_events_supported must be true or false");
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
trace_exporter_t *wrapper;
|
|
1779
|
+
TypedData_Get_Struct(self, trace_exporter_t, &trace_exporter_typed_data,
|
|
1780
|
+
wrapper);
|
|
1781
|
+
if (wrapper == NULL || wrapper->exporter == NULL) {
|
|
1782
|
+
raise_error(rb_eRuntimeError,
|
|
1783
|
+
"TraceExporter has not been initialized or was already freed");
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
long trace_count = RARRAY_LEN(traces);
|
|
1787
|
+
|
|
1788
|
+
/* Empty batch -> empty response (matches existing transport behaviour) */
|
|
1789
|
+
if (trace_count == 0) {
|
|
1790
|
+
return rb_ary_new();
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
/* Allocate trace chunks */
|
|
1794
|
+
ddog_TracerTraceChunks *chunks = NULL;
|
|
1795
|
+
ddog_TraceExporterError *chunks_err =
|
|
1796
|
+
ddog_tracer_trace_chunks_new((size_t)trace_count, &chunks);
|
|
1797
|
+
if (chunks_err != NULL) {
|
|
1798
|
+
ddog_trace_exporter_error_free(chunks_err);
|
|
1799
|
+
raise_error(rb_eRuntimeError, "Failed to allocate trace chunks");
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
send_traces_ctx ctx = {
|
|
1803
|
+
.exporter = wrapper->exporter,
|
|
1804
|
+
.traces = traces,
|
|
1805
|
+
.native_events_supported = native_events_supported,
|
|
1806
|
+
.trace_count = trace_count,
|
|
1807
|
+
.span_owner = {.span = NULL},
|
|
1808
|
+
.chunks = chunks,
|
|
1809
|
+
};
|
|
1810
|
+
|
|
1811
|
+
return rb_ensure(
|
|
1812
|
+
build_and_send_traces, (VALUE)&ctx,
|
|
1813
|
+
free_send_resources, (VALUE)&ctx);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
/* ========================================================================
|
|
1817
|
+
* Initialization
|
|
1818
|
+
* ======================================================================== */
|
|
1819
|
+
|
|
1820
|
+
void trace_exporter_init(VALUE tracing_module) {
|
|
1821
|
+
/* -- Module hierarchy -- */
|
|
1822
|
+
VALUE transport_module = rb_define_module_under(tracing_module, "Transport");
|
|
1823
|
+
VALUE native_module =
|
|
1824
|
+
rb_define_module_under(transport_module, "Native");
|
|
1825
|
+
|
|
1826
|
+
/* ----------------------------------------------------------------
|
|
1827
|
+
* TracerSpan class
|
|
1828
|
+
* ---------------------------------------------------------------- */
|
|
1829
|
+
tracer_span_class =
|
|
1830
|
+
rb_define_class_under(native_module, "TracerSpan", rb_cObject);
|
|
1831
|
+
rb_undef_alloc_func(tracer_span_class);
|
|
1832
|
+
|
|
1833
|
+
/* Factory */
|
|
1834
|
+
rb_define_singleton_method(tracer_span_class, "_native_from_span",
|
|
1835
|
+
_native_from_span, 1);
|
|
1836
|
+
|
|
1837
|
+
/* ----------------------------------------------------------------
|
|
1838
|
+
* TraceExporter class
|
|
1839
|
+
* ---------------------------------------------------------------- */
|
|
1840
|
+
trace_exporter_class =
|
|
1841
|
+
rb_define_class_under(native_module, "TraceExporter", rb_cObject);
|
|
1842
|
+
rb_undef_alloc_func(trace_exporter_class);
|
|
1843
|
+
|
|
1844
|
+
/* Factory: _native_new(url:, tracer_version:, ...) */
|
|
1845
|
+
rb_define_singleton_method(trace_exporter_class, "_native_new",
|
|
1846
|
+
_native_exporter_new, -1);
|
|
1847
|
+
|
|
1848
|
+
/* Instance: _native_send_traces(traces, native_events_supported) -> Array[Response] */
|
|
1849
|
+
rb_define_method(trace_exporter_class, "_native_send_traces",
|
|
1850
|
+
_native_send_traces, 2);
|
|
1851
|
+
|
|
1852
|
+
/* Instance: fork safety hooks */
|
|
1853
|
+
rb_define_method(trace_exporter_class, "_native_before_fork",
|
|
1854
|
+
_native_before_fork, 0);
|
|
1855
|
+
rb_define_method(trace_exporter_class, "_native_after_fork_in_parent",
|
|
1856
|
+
_native_after_fork_in_parent, 0);
|
|
1857
|
+
rb_define_method(trace_exporter_class, "_native_after_fork_in_child",
|
|
1858
|
+
_native_after_fork_in_child, 0);
|
|
1859
|
+
|
|
1860
|
+
/* ----------------------------------------------------------------
|
|
1861
|
+
* Response class (defined in Ruby, loaded lazily)
|
|
1862
|
+
*
|
|
1863
|
+
* We resolve it here so create_ok_response / create_error_response
|
|
1864
|
+
* can call Response.new without repeated const lookups.
|
|
1865
|
+
* ---------------------------------------------------------------- */
|
|
1866
|
+
rb_require("datadog/tracing/transport/native/response");
|
|
1867
|
+
response_class =
|
|
1868
|
+
rb_const_get(native_module, rb_intern("Response"));
|
|
1869
|
+
rb_global_variable(&response_class);
|
|
1870
|
+
|
|
1871
|
+
/* ----------------------------------------------------------------
|
|
1872
|
+
* Cache Ruby intern IDs
|
|
1873
|
+
* ---------------------------------------------------------------- */
|
|
1874
|
+
|
|
1875
|
+
/* Span ivars */
|
|
1876
|
+
at_name_id = rb_intern("@name");
|
|
1877
|
+
at_service_id = rb_intern("@service");
|
|
1878
|
+
at_resource_id = rb_intern("@resource");
|
|
1879
|
+
at_type_id = rb_intern("@type");
|
|
1880
|
+
at_id_id = rb_intern("@id");
|
|
1881
|
+
at_parent_id_id = rb_intern("@parent_id");
|
|
1882
|
+
at_trace_id_id = rb_intern("@trace_id");
|
|
1883
|
+
at_start_time_id = rb_intern("@start_time");
|
|
1884
|
+
at_duration_id = rb_intern("@duration");
|
|
1885
|
+
at_status_id = rb_intern("@status");
|
|
1886
|
+
at_meta_id = rb_intern("@meta");
|
|
1887
|
+
at_metrics_id = rb_intern("@metrics");
|
|
1888
|
+
at_events_id = rb_intern("@events");
|
|
1889
|
+
at_links_id = rb_intern("@links");
|
|
1890
|
+
at_metastruct_id = rb_intern("@metastruct");
|
|
1891
|
+
|
|
1892
|
+
/* Methods */
|
|
1893
|
+
id_duration_method = rb_intern("duration");
|
|
1894
|
+
id_to_a = rb_intern("to_a");
|
|
1895
|
+
id_to_native_format = rb_intern("to_native_format");
|
|
1896
|
+
id_to_hash = rb_intern("to_hash");
|
|
1897
|
+
id_to_h = rb_intern("to_h");
|
|
1898
|
+
id_negative_p = rb_intern("negative?");
|
|
1899
|
+
|
|
1900
|
+
event_name_key = rb_str_new_cstr("name");
|
|
1901
|
+
event_time_key = rb_str_new_cstr("time_unix_nano");
|
|
1902
|
+
event_attributes_key = rb_str_new_cstr("attributes");
|
|
1903
|
+
rb_global_variable(&event_name_key);
|
|
1904
|
+
rb_global_variable(&event_time_key);
|
|
1905
|
+
rb_global_variable(&event_attributes_key);
|
|
1906
|
+
event_type_id = rb_intern("type");
|
|
1907
|
+
event_string_value_id = rb_intern("string_value");
|
|
1908
|
+
event_bool_value_id = rb_intern("bool_value");
|
|
1909
|
+
event_int_value_id = rb_intern("int_value");
|
|
1910
|
+
event_double_value_id = rb_intern("double_value");
|
|
1911
|
+
event_array_value_id = rb_intern("array_value");
|
|
1912
|
+
event_values_id = rb_intern("values");
|
|
1913
|
+
|
|
1914
|
+
/* SpanLink#to_hash fields */
|
|
1915
|
+
link_trace_id_id = rb_intern("trace_id");
|
|
1916
|
+
link_trace_id_high_id = rb_intern("trace_id_high");
|
|
1917
|
+
link_span_id_id = rb_intern("span_id");
|
|
1918
|
+
link_attributes_id = rb_intern("attributes");
|
|
1919
|
+
link_tracestate_id = rb_intern("tracestate");
|
|
1920
|
+
link_flags_id = rb_intern("flags");
|
|
1921
|
+
|
|
1922
|
+
/* Response.new */
|
|
1923
|
+
id_new = rb_intern("new");
|
|
1924
|
+
|
|
1925
|
+
/* Response keyword-argument IDs */
|
|
1926
|
+
kw_ok = rb_intern("ok");
|
|
1927
|
+
kw_internal_error = rb_intern("internal_error");
|
|
1928
|
+
kw_server_error = rb_intern("server_error");
|
|
1929
|
+
kw_client_error = rb_intern("client_error");
|
|
1930
|
+
kw_trace_count = rb_intern("trace_count");
|
|
1931
|
+
kw_payload = rb_intern("payload");
|
|
1932
|
+
}
|