datadog 2.7.1 → 2.18.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 +353 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +78 -102
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +235 -57
- data/ext/datadog_profiling_native_extension/collectors_stack.h +21 -5
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +376 -156
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +14 -8
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
- data/ext/datadog_profiling_native_extension/heap_recorder.c +295 -532
- data/ext/datadog_profiling_native_extension/heap_recorder.h +6 -8
- data/ext/datadog_profiling_native_extension/http_transport.c +64 -98
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +69 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +16 -4
- data/ext/datadog_profiling_native_extension/profiling.c +19 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +9 -21
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +2 -10
- data/ext/datadog_profiling_native_extension/stack_recorder.c +231 -181
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +17 -15
- data/ext/libdatadog_api/crashtracker.h +5 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/init.c +15 -0
- data/ext/libdatadog_api/library_config.c +164 -0
- data/ext/libdatadog_api/library_config.h +25 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +112 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
- data/lib/datadog/appsec/actions_handler.rb +49 -0
- data/lib/datadog/appsec/anonymizer.rb +16 -0
- data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +65 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +23 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +623 -253
- data/lib/datadog/appsec/assets/waf_rules/strict.json +69 -107
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +49 -65
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +212 -27
- data/lib/datadog/appsec/context.rb +74 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +92 -0
- data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +101 -0
- data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
- data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
- data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
- data/lib/datadog/appsec/contrib/devise/patcher.rb +33 -25
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
- data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
- data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +42 -0
- data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
- data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +41 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +17 -30
- data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +78 -98
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +73 -78
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +16 -33
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +25 -38
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +38 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +31 -68
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -31
- data/lib/datadog/appsec/event.rb +96 -135
- data/lib/datadog/appsec/ext.rb +12 -3
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
- data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
- data/lib/datadog/appsec/metrics/collector.rb +38 -0
- data/lib/datadog/appsec/metrics/exporter.rb +35 -0
- data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
- data/lib/datadog/appsec/metrics.rb +13 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +52 -32
- data/lib/datadog/appsec/processor/rule_loader.rb +30 -36
- data/lib/datadog/appsec/remote.rb +31 -57
- data/lib/datadog/appsec/response.rb +19 -85
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/result.rb +67 -0
- data/lib/datadog/appsec/security_engine/runner.rb +87 -0
- data/lib/datadog/appsec/security_engine.rb +9 -0
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec/utils.rb +0 -2
- data/lib/datadog/appsec.rb +22 -12
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -18
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +74 -32
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/ext.rb +5 -1
- data/lib/datadog/core/configuration/option.rb +81 -45
- data/lib/datadog/core/configuration/option_definition.rb +6 -4
- data/lib/datadog/core/configuration/options.rb +3 -3
- data/lib/datadog/core/configuration/settings.rb +121 -50
- data/lib/datadog/core/configuration/stable_config.rb +22 -0
- data/lib/datadog/core/configuration.rb +43 -11
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +4 -13
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/encoding.rb +17 -1
- data/lib/datadog/core/environment/agent_info.rb +78 -0
- data/lib/datadog/core/environment/cgroup.rb +10 -12
- data/lib/datadog/core/environment/container.rb +38 -40
- data/lib/datadog/core/environment/ext.rb +6 -6
- data/lib/datadog/core/environment/git.rb +1 -0
- data/lib/datadog/core/environment/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/environment/variable_helpers.rb +1 -1
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +27 -27
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +36 -0
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client/capabilities.rb +6 -0
- data/lib/datadog/core/remote/client.rb +107 -92
- data/lib/datadog/core/remote/component.rb +18 -19
- data/lib/datadog/core/remote/configuration/digest.rb +7 -7
- data/lib/datadog/core/remote/configuration/path.rb +1 -1
- data/lib/datadog/core/remote/configuration/repository.rb +14 -1
- data/lib/datadog/core/remote/negotiation.rb +9 -9
- data/lib/datadog/core/remote/transport/config.rb +4 -3
- data/lib/datadog/core/remote/transport/http/api.rb +13 -18
- data/lib/datadog/core/remote/transport/http/client.rb +5 -4
- data/lib/datadog/core/remote/transport/http/config.rb +27 -55
- data/lib/datadog/core/remote/transport/http/negotiation.rb +8 -51
- data/lib/datadog/core/remote/transport/http.rb +25 -94
- data/lib/datadog/core/remote/transport/negotiation.rb +17 -4
- data/lib/datadog/core/remote/worker.rb +10 -7
- data/lib/datadog/core/runtime/metrics.rb +12 -5
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +84 -49
- data/lib/datadog/core/telemetry/emitter.rb +23 -11
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +269 -0
- data/lib/datadog/core/telemetry/event/base.rb +40 -0
- data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
- data/lib/datadog/core/telemetry/event/log.rb +76 -0
- data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
- data/lib/datadog/core/telemetry/event.rb +17 -383
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +12 -6
- data/lib/datadog/core/telemetry/metric.rb +28 -6
- data/lib/datadog/core/telemetry/request.rb +4 -4
- data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
- data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
- data/lib/datadog/core/telemetry/transport/http.rb +63 -0
- data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
- data/lib/datadog/core/telemetry/worker.rb +128 -25
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
- data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +18 -1
- data/lib/datadog/core/transport/http/api/spec.rb +36 -0
- data/lib/datadog/{tracing → core}/transport/http/builder.rb +53 -31
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/transport/http.rb +75 -0
- data/lib/datadog/core/transport/response.rb +4 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
- data/lib/datadog/core/utils/duration.rb +32 -32
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/network.rb +6 -6
- data/lib/datadog/core/utils/only_once_successful.rb +16 -5
- data/lib/datadog/core/utils/time.rb +20 -0
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/utils.rb +7 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
- data/lib/datadog/core/worker.rb +1 -1
- data/lib/datadog/core/workers/async.rb +29 -12
- data/lib/datadog/core/workers/interval_loop.rb +12 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
- data/lib/datadog/core.rb +8 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/boot.rb +34 -0
- data/lib/datadog/di/code_tracker.rb +26 -15
- data/lib/datadog/di/component.rb +23 -14
- data/lib/datadog/di/configuration/settings.rb +25 -1
- data/lib/datadog/di/contrib/active_record.rb +1 -0
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +28 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +162 -21
- data/lib/datadog/di/logger.rb +30 -0
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +14 -7
- data/lib/datadog/di/probe_builder.rb +1 -0
- data/lib/datadog/di/probe_manager.rb +11 -5
- data/lib/datadog/di/probe_notification_builder.rb +54 -38
- data/lib/datadog/di/probe_notifier_worker.rb +60 -26
- data/lib/datadog/di/redactor.rb +0 -1
- data/lib/datadog/di/remote.rb +147 -0
- data/lib/datadog/di/serializer.rb +19 -8
- data/lib/datadog/di/transport/diagnostics.rb +62 -0
- data/lib/datadog/di/transport/http/api.rb +42 -0
- data/lib/datadog/di/transport/http/client.rb +47 -0
- data/lib/datadog/di/transport/http/diagnostics.rb +65 -0
- data/lib/datadog/di/transport/http/input.rb +77 -0
- data/lib/datadog/di/transport/http.rb +57 -0
- data/lib/datadog/di/transport/input.rb +70 -0
- data/lib/datadog/di/utils.rb +103 -0
- data/lib/datadog/di.rb +14 -76
- data/lib/datadog/error_tracking/collector.rb +87 -0
- data/lib/datadog/error_tracking/component.rb +167 -0
- data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
- data/lib/datadog/error_tracking/configuration.rb +11 -0
- data/lib/datadog/error_tracking/ext.rb +18 -0
- data/lib/datadog/error_tracking/extensions.rb +16 -0
- data/lib/datadog/error_tracking/filters.rb +77 -0
- data/lib/datadog/error_tracking.rb +18 -0
- data/lib/datadog/kit/appsec/events.rb +15 -3
- data/lib/datadog/kit/identity.rb +9 -5
- data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
- data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
- data/lib/datadog/opentelemetry/api/context.rb +16 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
- data/lib/datadog/opentelemetry.rb +2 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +18 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/info.rb +3 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +17 -2
- data/lib/datadog/profiling/component.rb +64 -82
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +3 -4
- data/lib/datadog/profiling/ext.rb +0 -14
- data/lib/datadog/profiling/flush.rb +5 -8
- data/lib/datadog/profiling/http_transport.rb +8 -87
- data/lib/datadog/profiling/load_native_extension.rb +1 -33
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +10 -2
- data/lib/datadog/profiling/stack_recorder.rb +9 -9
- data/lib/datadog/profiling/tag_builder.rb +5 -41
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/profiling.rb +6 -2
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/component.rb +16 -12
- data/lib/datadog/tracing/configuration/ext.rb +8 -1
- data/lib/datadog/tracing/configuration/settings.rb +22 -10
- data/lib/datadog/tracing/context_provider.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +7 -3
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -2
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +36 -1
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +14 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
- data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
- data/lib/datadog/tracing/contrib/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/extensions.rb +29 -3
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
- data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
- data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
- data/lib/datadog/tracing/contrib/karafka.rb +37 -0
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/correlation.rb +9 -2
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +131 -0
- data/lib/datadog/tracing/distributed/datadog.rb +4 -2
- data/lib/datadog/tracing/distributed/propagation.rb +25 -4
- data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/tracing/metadata/ext.rb +5 -0
- data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
- data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
- data/lib/datadog/tracing/metadata.rb +2 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
- data/lib/datadog/tracing/span.rb +22 -5
- data/lib/datadog/tracing/span_event.rb +124 -4
- data/lib/datadog/tracing/span_operation.rb +52 -16
- data/lib/datadog/tracing/sync_writer.rb +10 -6
- data/lib/datadog/tracing/trace_digest.rb +9 -2
- data/lib/datadog/tracing/trace_operation.rb +55 -27
- data/lib/datadog/tracing/trace_segment.rb +6 -4
- data/lib/datadog/tracing/tracer.rb +66 -14
- data/lib/datadog/tracing/transport/http/api.rb +5 -4
- data/lib/datadog/tracing/transport/http/client.rb +5 -4
- data/lib/datadog/tracing/transport/http/traces.rb +13 -44
- data/lib/datadog/tracing/transport/http.rb +13 -70
- data/lib/datadog/tracing/transport/serializable_trace.rb +31 -7
- data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
- data/lib/datadog/tracing/transport/traces.rb +47 -13
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers/trace_writer.rb +8 -5
- data/lib/datadog/tracing/workers.rb +5 -4
- data/lib/datadog/tracing/writer.rb +10 -6
- data/lib/datadog/tracing.rb +16 -3
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +2 -0
- metadata +149 -54
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
- data/ext/datadog_profiling_loader/extconf.rb +0 -60
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
- data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
- data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
- data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
- data/lib/datadog/appsec/contrib/patcher.rb +0 -12
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
- data/lib/datadog/appsec/processor/actions.rb +0 -49
- data/lib/datadog/appsec/processor/context.rb +0 -107
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
- data/lib/datadog/appsec/processor.rb +0 -106
- data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
- data/lib/datadog/appsec/reactive/engine.rb +0 -47
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
- data/lib/datadog/appsec/scope.rb +0 -58
- data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
- data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
- data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
- data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
- data/lib/datadog/core/telemetry/http/env.rb +0 -20
- data/lib/datadog/core/telemetry/http/ext.rb +0 -28
- data/lib/datadog/core/telemetry/http/response.rb +0 -70
- data/lib/datadog/core/telemetry/http/transport.rb +0 -90
- data/lib/datadog/di/transport.rb +0 -81
- data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../metadata/ext'
|
4
|
+
require_relative '../trace_digest'
|
5
|
+
require_relative 'datadog_tags_codec'
|
6
|
+
require_relative '../utils'
|
7
|
+
require_relative 'helpers'
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
module Datadog
|
11
|
+
module Tracing
|
12
|
+
module Distributed
|
13
|
+
# W3C Baggage propagator implementation.
|
14
|
+
# The baggage header is propagated through `baggage`.
|
15
|
+
# @see https://www.w3.org/TR/baggage/
|
16
|
+
class Baggage
|
17
|
+
BAGGAGE_KEY = 'baggage'
|
18
|
+
DD_TRACE_BAGGAGE_MAX_ITEMS = 64
|
19
|
+
DD_TRACE_BAGGAGE_MAX_BYTES = 8192
|
20
|
+
SAFE_CHARACTERS_KEY = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$!#&'*+-.^_`|~"
|
21
|
+
SAFE_CHARACTERS_VALUE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$!#&'()*+-./:<>?@[]^_`{|}~"
|
22
|
+
|
23
|
+
def initialize(
|
24
|
+
fetcher:,
|
25
|
+
baggage_key: BAGGAGE_KEY
|
26
|
+
)
|
27
|
+
@baggage_key = baggage_key
|
28
|
+
@fetcher = fetcher
|
29
|
+
end
|
30
|
+
|
31
|
+
def inject!(digest, data)
|
32
|
+
return if digest.nil? || digest.baggage.nil?
|
33
|
+
|
34
|
+
baggage_items = digest.baggage.reject { |k, v| k.nil? || v.nil? }
|
35
|
+
return if baggage_items.empty?
|
36
|
+
|
37
|
+
begin
|
38
|
+
if baggage_items.size > DD_TRACE_BAGGAGE_MAX_ITEMS
|
39
|
+
::Datadog.logger.warn('Baggage item limit exceeded, dropping excess items')
|
40
|
+
baggage_items = baggage_items.first(DD_TRACE_BAGGAGE_MAX_ITEMS)
|
41
|
+
end
|
42
|
+
|
43
|
+
encoded_items = []
|
44
|
+
total_size = 0
|
45
|
+
|
46
|
+
baggage_items.each do |key, value|
|
47
|
+
item = "#{encode_item(key, SAFE_CHARACTERS_KEY)}=#{encode_item(value, SAFE_CHARACTERS_VALUE)}"
|
48
|
+
item_size = item.bytesize + (encoded_items.empty? ? 0 : 1) # +1 for comma if not first item
|
49
|
+
if total_size + item_size > DD_TRACE_BAGGAGE_MAX_BYTES
|
50
|
+
::Datadog.logger.warn('Baggage header size exceeded, dropping excess items')
|
51
|
+
break # stop adding items when size limit is reached
|
52
|
+
end
|
53
|
+
encoded_items << item
|
54
|
+
total_size += item_size
|
55
|
+
end
|
56
|
+
|
57
|
+
# edge case where a single item is too large
|
58
|
+
return if encoded_items.empty?
|
59
|
+
|
60
|
+
header_value = encoded_items.join(',')
|
61
|
+
data[@baggage_key] = header_value
|
62
|
+
rescue => e
|
63
|
+
::Datadog.logger.warn("Failed to encode and inject baggage header: #{e.message}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def extract(data)
|
68
|
+
fetcher = @fetcher.new(data)
|
69
|
+
data = fetcher[@baggage_key]
|
70
|
+
return unless data
|
71
|
+
|
72
|
+
baggage = parse_baggage_header(fetcher[@baggage_key])
|
73
|
+
return unless baggage
|
74
|
+
|
75
|
+
TraceDigest.new(
|
76
|
+
baggage: baggage,
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def encode_item(item, safe_characters)
|
83
|
+
# Strip whitespace and URL-encode the item
|
84
|
+
result = URI.encode_www_form_component(item.strip)
|
85
|
+
# Replace '+' with '%20' for space encoding consistency with W3C spec
|
86
|
+
result = result.gsub('+', '%20')
|
87
|
+
# Selectively decode percent-encoded characters that are considered "safe" in W3C Baggage spec
|
88
|
+
result.gsub(/%[0-9A-F]{2}/) do |encoded|
|
89
|
+
if encoded.size >= 3 && encoded[1..2] =~ /\A[0-9A-F]{2}\z/
|
90
|
+
hex_str = encoded[1..2]
|
91
|
+
next encoded unless hex_str && !hex_str.empty?
|
92
|
+
|
93
|
+
# Convert hex representation back to character
|
94
|
+
char = [hex_str.hex].pack('C')
|
95
|
+
# Keep the character as-is if it's in the safe character set, otherwise keep it encoded
|
96
|
+
safe_characters.include?(char) ? char : encoded
|
97
|
+
else
|
98
|
+
encoded
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Parses a W3C Baggage header string into a hash of key-value pairs
|
104
|
+
# The header format follows the W3C Baggage specification:
|
105
|
+
# - Multiple baggage items are separated by commas
|
106
|
+
# - Each baggage item is a key-value pair separated by '='
|
107
|
+
# - Keys and values are URL-encoded
|
108
|
+
# - Returns an empty hash if the baggage header is malformed
|
109
|
+
#
|
110
|
+
# @param baggage_header [String] The W3C Baggage header string to parse
|
111
|
+
# @return [Hash<String, String>] A hash of decoded baggage items
|
112
|
+
def parse_baggage_header(baggage_header)
|
113
|
+
baggage = {}
|
114
|
+
baggages = baggage_header.split(',')
|
115
|
+
baggages.each do |key_value|
|
116
|
+
key, value = key_value.split('=', 2)
|
117
|
+
# If baggage is malformed, return an empty hash
|
118
|
+
return {} unless key && value
|
119
|
+
|
120
|
+
key = URI.decode_www_form_component(key.strip)
|
121
|
+
value = URI.decode_www_form_component(value.strip)
|
122
|
+
return {} if key.empty? || value.empty?
|
123
|
+
|
124
|
+
baggage[key] = value
|
125
|
+
end
|
126
|
+
baggage
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -89,7 +89,7 @@ module Datadog
|
|
89
89
|
trace_id = Helpers.parse_decimal_id(fetcher_object[@trace_id_key])
|
90
90
|
|
91
91
|
return unless trace_id
|
92
|
-
return if trace_id <= 0 || trace_id
|
92
|
+
return if trace_id <= 0 || trace_id > Tracing::Utils::EXTERNAL_MAX_ID
|
93
93
|
|
94
94
|
trace_id
|
95
95
|
end
|
@@ -98,7 +98,7 @@ module Datadog
|
|
98
98
|
parent_id = Helpers.parse_decimal_id(fetcher_object[@parent_id_key])
|
99
99
|
|
100
100
|
return unless parent_id
|
101
|
-
return if parent_id <= 0 || parent_id
|
101
|
+
return if parent_id <= 0 || parent_id > Tracing::Utils::EXTERNAL_MAX_ID
|
102
102
|
|
103
103
|
parent_id
|
104
104
|
end
|
@@ -116,6 +116,8 @@ module Datadog
|
|
116
116
|
def extract_trace_id!(trace_id, tags)
|
117
117
|
return trace_id unless tags
|
118
118
|
return trace_id unless (high_order = tags.delete(Tracing::Metadata::Ext::Distributed::TAG_TID))
|
119
|
+
return trace_id unless high_order.size == 16
|
120
|
+
return trace_id unless /\A[0-9a-f]+\z/i.match?(high_order)
|
119
121
|
|
120
122
|
Tracing::Utils::TraceId.concatenate(high_order.to_i(16), trace_id)
|
121
123
|
end
|
@@ -4,6 +4,7 @@ require_relative '../configuration/ext'
|
|
4
4
|
require_relative '../trace_digest'
|
5
5
|
require_relative '../trace_operation'
|
6
6
|
require_relative '../../core/telemetry/logger'
|
7
|
+
require_relative 'baggage'
|
7
8
|
|
8
9
|
module Datadog
|
9
10
|
module Tracing
|
@@ -26,9 +27,13 @@ module Datadog
|
|
26
27
|
)
|
27
28
|
@propagation_styles = propagation_styles
|
28
29
|
@propagation_extract_first = propagation_extract_first
|
29
|
-
|
30
30
|
@propagation_style_inject = propagation_style_inject.map { |style| propagation_styles[style] }
|
31
31
|
@propagation_style_extract = propagation_style_extract.map { |style| propagation_styles[style] }
|
32
|
+
|
33
|
+
# The baggage propagator is unique in that baggage should always be extracted, if present.
|
34
|
+
# Therefore we remove it from the `propagation_style_extract` list.
|
35
|
+
@baggage_propagator = @propagation_style_extract.find { |propagator| propagator.is_a?(Baggage) }
|
36
|
+
@propagation_style_extract.delete(@baggage_propagator) if @baggage_propagator
|
32
37
|
end
|
33
38
|
|
34
39
|
# inject! populates the env with span ID, trace ID and sampling priority
|
@@ -57,9 +62,8 @@ module Datadog
|
|
57
62
|
end
|
58
63
|
|
59
64
|
digest = digest.to_digest if digest.respond_to?(:to_digest)
|
60
|
-
|
61
|
-
|
62
|
-
::Datadog.logger.debug('Cannot inject distributed trace data: digest.trace_id is nil.')
|
65
|
+
if digest.trace_id.nil? && digest.baggage.nil?
|
66
|
+
::Datadog.logger.debug('Cannot inject distributed trace data: digest.trace_id and digest.baggage are both nil.')
|
63
67
|
return nil
|
64
68
|
end
|
65
69
|
|
@@ -138,12 +142,29 @@ module Datadog
|
|
138
142
|
"Error extracting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
|
139
143
|
)
|
140
144
|
end
|
145
|
+
# Handle baggage after all other styles if present
|
146
|
+
extracted_trace_digest = propagate_baggage(data, extracted_trace_digest) if @baggage_propagator
|
141
147
|
|
142
148
|
extracted_trace_digest
|
143
149
|
end
|
144
150
|
|
145
151
|
private
|
146
152
|
|
153
|
+
def propagate_baggage(data, extracted_trace_digest)
|
154
|
+
if extracted_trace_digest
|
155
|
+
# Merge with baggage if present
|
156
|
+
digest = @baggage_propagator.extract(data)
|
157
|
+
if digest
|
158
|
+
extracted_trace_digest.merge(baggage: digest.baggage)
|
159
|
+
else
|
160
|
+
extracted_trace_digest
|
161
|
+
end
|
162
|
+
else
|
163
|
+
# Baggage is the only style
|
164
|
+
@baggage_propagator.extract(data)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
147
168
|
def last_datadog_parent_id(headers, tracecontext_tags)
|
148
169
|
dd_propagator = @propagation_style_extract.find { |propagator| propagator.is_a?(Datadog) }
|
149
170
|
if tracecontext_tags&.fetch(
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Tracing
|
5
|
+
module Distributed
|
6
|
+
# Helper method to decide when to skip distributed tracing
|
7
|
+
module PropagationPolicy
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Skips distributed tracing if disabled for this instrumentation
|
11
|
+
# or if APM is disabled unless there is an AppSec event (from upstream distributed trace or local)
|
12
|
+
#
|
13
|
+
# Both pin_config and global_config are configuration for integrations.
|
14
|
+
# pin_config is a Datadog::Core::Pin object, which gives the configuration of a single instance of an integration.
|
15
|
+
# global_config is the config for all instances of an integration.
|
16
|
+
def enabled?(pin_config: nil, global_config: nil, trace: nil)
|
17
|
+
return false unless Tracing.enabled?
|
18
|
+
|
19
|
+
unless ::Datadog.configuration.apm.tracing.enabled
|
20
|
+
return false if trace.nil?
|
21
|
+
|
22
|
+
trace_source = trace.get_tag(::Datadog::Tracing::Metadata::Ext::Distributed::TAG_TRACE_SOURCE)&.to_i(16)
|
23
|
+
return false if trace_source.nil?
|
24
|
+
|
25
|
+
# If AppSec is enabled and AppSec bit is set in the trace, we should not skip distributed tracing
|
26
|
+
# Other products that will use dd.p.ts should implement similar behavior here
|
27
|
+
if ::Datadog.configuration.appsec.enabled && (trace_source & ::Datadog::AppSec::Ext::PRODUCT_BIT) != 0
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
|
34
|
+
return pin_config[:distributed_tracing] if pin_config && pin_config.key?(:distributed_tracing)
|
35
|
+
return global_config[:distributed_tracing] if global_config
|
36
|
+
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -10,17 +10,17 @@ module Datadog
|
|
10
10
|
# Adds error tagging behavior
|
11
11
|
# @public_api
|
12
12
|
module Errors
|
13
|
-
def set_error(
|
13
|
+
def set_error(error)
|
14
14
|
Datadog::Core.log_deprecation do
|
15
15
|
'Errors.set_error(..) is deprecated. ' \
|
16
16
|
'Use Errors.set_error_tags(..) instead.'
|
17
17
|
end
|
18
|
-
set_error_tags(
|
18
|
+
set_error_tags(error)
|
19
19
|
end
|
20
20
|
|
21
21
|
# Mark the span with the given error.
|
22
|
-
def set_error_tags(
|
23
|
-
e = Core::Error.build_from(
|
22
|
+
def set_error_tags(error)
|
23
|
+
e = Core::Error.build_from(error)
|
24
24
|
|
25
25
|
set_tag(Ext::Errors::TAG_TYPE, e.type) unless e.type.empty?
|
26
26
|
set_tag(Ext::Errors::TAG_MSG, e.message) unless e.message.empty?
|
@@ -31,6 +31,8 @@ module Datadog
|
|
31
31
|
# See Datadog-internal "RFC: Identifying which spans have profiling enabled " for details
|
32
32
|
TAG_PROFILING_ENABLED = '_dd.profiling.enabled'
|
33
33
|
|
34
|
+
TAG_APM_ENABLED = '_dd.apm.enabled'
|
35
|
+
|
34
36
|
# Defines constants for trace analytics
|
35
37
|
# @public_api
|
36
38
|
module Analytics
|
@@ -55,6 +57,9 @@ module Datadog
|
|
55
57
|
# @see Datadog::Tracing::Sampling::Ext::Mechanism
|
56
58
|
TAG_DECISION_MAKER = '_dd.p.dm'
|
57
59
|
|
60
|
+
# Bitmask for which product generated an event. E.g.: 2 for an AppSec event.
|
61
|
+
TAG_TRACE_SOURCE = '_dd.p.ts'
|
62
|
+
|
58
63
|
TAG_ORIGIN = '_dd.origin'
|
59
64
|
TAG_SAMPLING_PRIORITY = '_sampling_priority_v1'
|
60
65
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Tracing
|
7
|
+
module Metadata
|
8
|
+
# This class is a data structure that is used to store
|
9
|
+
# complex metadata, such as an array of objects.
|
10
|
+
#
|
11
|
+
# It is serialized to MessagePack format when sent to the agent.
|
12
|
+
class Metastruct
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
def_delegators :@metastruct, :[], :[]=, :to_h
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@metastruct = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_msgpack(packer = nil)
|
22
|
+
# JRuby doesn't pass the packer
|
23
|
+
packer ||= MessagePack::Packer.new
|
24
|
+
|
25
|
+
packer.write(@metastruct.transform_values(&:to_msgpack))
|
26
|
+
end
|
27
|
+
|
28
|
+
def pretty_print(q)
|
29
|
+
q.seplist @metastruct.each do |key, value|
|
30
|
+
q.text "#{key} => #{value}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'metastruct'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Tracing
|
7
|
+
module Metadata
|
8
|
+
# Adds data storage for the `meta_struct` field.
|
9
|
+
#
|
10
|
+
# This field is used to send more complex data like an array of objects
|
11
|
+
# in MessagePack format to the agent, and has no size limitations.
|
12
|
+
#
|
13
|
+
# The agent fully supports meta_struct from version v7.35.0 (April 2022).
|
14
|
+
#
|
15
|
+
# On versions older than v7.35.0, sending traces containing meta_struct
|
16
|
+
# has no unexpected side-effects; traces are sent to the backend as expected,
|
17
|
+
# while the meta_struct field is stripped.
|
18
|
+
module MetastructTagging
|
19
|
+
# Set the given key / value tag pair on the metastruct.
|
20
|
+
#
|
21
|
+
# A valid example is:
|
22
|
+
#
|
23
|
+
# span.set_metastruct_tag('_dd.stack', [])
|
24
|
+
def set_metastruct_tag(key, value)
|
25
|
+
metastruct[key] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return the metastruct tag value for the given key,
|
29
|
+
# returns nil if the key doesn't exist.
|
30
|
+
def get_metastruct_tag(key)
|
31
|
+
metastruct[key]
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def metastruct
|
37
|
+
@metastruct ||= Metastruct.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'metadata/analytics'
|
4
4
|
require_relative 'metadata/tagging'
|
5
|
+
require_relative 'metadata/metastruct_tagging'
|
5
6
|
require_relative 'metadata/errors'
|
6
7
|
|
7
8
|
module Datadog
|
@@ -10,6 +11,7 @@ module Datadog
|
|
10
11
|
module Metadata
|
11
12
|
def self.included(base)
|
12
13
|
base.include(Metadata::Tagging)
|
14
|
+
base.include(Metadata::MetastructTagging)
|
13
15
|
base.include(Metadata::Errors)
|
14
16
|
|
15
17
|
# Additional extensions
|
@@ -9,6 +9,7 @@ module Datadog
|
|
9
9
|
# {Datadog::Tracing::Sampling::RateSampler} is based on a sample rate.
|
10
10
|
class RateSampler < Sampler
|
11
11
|
KNUTH_FACTOR = 1111111111111111111
|
12
|
+
UINT64_MODULO = (1 << 64)
|
12
13
|
|
13
14
|
# Initialize a {Datadog::Tracing::Sampling::RateSampler}.
|
14
15
|
# This sampler keeps a random subset of the traces. Its main purpose is to
|
@@ -39,7 +40,7 @@ module Datadog
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def sample?(trace)
|
42
|
-
((trace.id * KNUTH_FACTOR) %
|
43
|
+
((trace.id * KNUTH_FACTOR) % UINT64_MODULO) <= @sampling_id_threshold
|
43
44
|
end
|
44
45
|
|
45
46
|
def sample!(trace)
|
data/lib/datadog/tracing/span.rb
CHANGED
@@ -33,6 +33,9 @@ module Datadog
|
|
33
33
|
:status,
|
34
34
|
:trace_id
|
35
35
|
|
36
|
+
attr_reader \
|
37
|
+
:metastruct
|
38
|
+
|
36
39
|
attr_writer \
|
37
40
|
:duration
|
38
41
|
|
@@ -54,6 +57,7 @@ module Datadog
|
|
54
57
|
id: nil,
|
55
58
|
meta: nil,
|
56
59
|
metrics: nil,
|
60
|
+
metastruct: nil,
|
57
61
|
parent_id: 0,
|
58
62
|
resource: name,
|
59
63
|
service: nil,
|
@@ -76,6 +80,7 @@ module Datadog
|
|
76
80
|
|
77
81
|
@meta = meta || {}
|
78
82
|
@metrics = metrics || {}
|
83
|
+
@metastruct = metastruct || {}
|
79
84
|
@status = status || 0
|
80
85
|
|
81
86
|
# start_time and end_time track wall clock. In Ruby, wall clock
|
@@ -112,7 +117,10 @@ module Datadog
|
|
112
117
|
|
113
118
|
def duration
|
114
119
|
return @duration if @duration
|
115
|
-
|
120
|
+
|
121
|
+
start_time = @start_time
|
122
|
+
end_time = @end_time
|
123
|
+
end_time - start_time if start_time && end_time
|
116
124
|
end
|
117
125
|
|
118
126
|
def set_error(e)
|
@@ -135,10 +143,13 @@ module Datadog
|
|
135
143
|
# TODO: Change this to reflect attributes when serialization
|
136
144
|
# isn't handled by this method.
|
137
145
|
def to_hash
|
146
|
+
@meta['events'] = @events.map(&:to_hash).to_json unless @events.empty?
|
147
|
+
|
138
148
|
h = {
|
139
149
|
error: @status,
|
140
150
|
meta: @meta,
|
141
151
|
metrics: @metrics,
|
152
|
+
meta_struct: @metastruct.to_h,
|
142
153
|
name: @name,
|
143
154
|
parent_id: @parent_id,
|
144
155
|
resource: @resource,
|
@@ -154,8 +165,6 @@ module Datadog
|
|
154
165
|
h[:duration] = duration_nano
|
155
166
|
end
|
156
167
|
|
157
|
-
h[:meta]['events'] = @events.map(&:to_hash).to_json unless @events.empty?
|
158
|
-
|
159
168
|
h
|
160
169
|
end
|
161
170
|
|
@@ -182,12 +191,15 @@ module Datadog
|
|
182
191
|
q.text "#{key} => #{value}"
|
183
192
|
end
|
184
193
|
end
|
185
|
-
q.group(2, 'Metrics: [',
|
194
|
+
q.group(2, 'Metrics: [', "]\n") do
|
186
195
|
q.breakable
|
187
196
|
q.seplist @metrics.each do |key, value|
|
188
197
|
q.text "#{key} => #{value}"
|
189
198
|
end
|
190
199
|
end
|
200
|
+
q.group(2, 'Metastruct: [', ']') do
|
201
|
+
metastruct.pretty_print(q)
|
202
|
+
end
|
191
203
|
end
|
192
204
|
end
|
193
205
|
|
@@ -196,12 +208,17 @@ module Datadog
|
|
196
208
|
# Used for serialization
|
197
209
|
# @return [Integer] in nanoseconds since Epoch
|
198
210
|
def start_time_nano
|
199
|
-
|
211
|
+
return unless (start_time = @start_time)
|
212
|
+
|
213
|
+
start_time.to_i * 1000000000 + start_time.nsec
|
200
214
|
end
|
201
215
|
|
202
216
|
# Used for serialization
|
203
217
|
# @return [Integer] in nanoseconds since Epoch
|
204
218
|
def duration_nano
|
219
|
+
duration = self.duration
|
220
|
+
return unless duration
|
221
|
+
|
205
222
|
(duration * 1e9).to_i
|
206
223
|
end
|
207
224
|
|
@@ -19,23 +19,143 @@ module Datadog
|
|
19
19
|
# @return [Integer]
|
20
20
|
attr_reader :time_unix_nano
|
21
21
|
|
22
|
+
# TODO: Accept {Time} as the time_unix_nano parameter, possibly in addition to the current nano integer.
|
22
23
|
def initialize(
|
23
24
|
name,
|
24
25
|
attributes: nil,
|
25
26
|
time_unix_nano: nil
|
26
27
|
)
|
27
28
|
@name = name
|
28
|
-
|
29
|
+
|
30
|
+
@attributes = attributes.dup || {}
|
31
|
+
validate_attributes!(@attributes)
|
32
|
+
@attributes.transform_keys!(&:to_s)
|
33
|
+
|
29
34
|
# OpenTelemetry SDK stores span event timestamps in nanoseconds (not seconds).
|
30
35
|
# We will do the same here to avoid unnecessary conversions and inconsistencies.
|
31
|
-
@time_unix_nano = time_unix_nano || (Time.now.to_r * 1_000_000_000).to_i
|
36
|
+
@time_unix_nano = time_unix_nano || (Core::Utils::Time.now.to_r * 1_000_000_000).to_i
|
32
37
|
end
|
33
38
|
|
39
|
+
# Converts the span event into a hash to be used by with the span tag serialization
|
40
|
+
# (`span.set_tag('events) = [event.to_hash]`). This serialization format has the drawback
|
41
|
+
# of being limiting span events to the size limit of a span tag.
|
42
|
+
# All Datadog agents support this format.
|
34
43
|
def to_hash
|
35
|
-
h = { name
|
36
|
-
h[
|
44
|
+
h = { 'name' => @name, 'time_unix_nano' => @time_unix_nano }
|
45
|
+
h['attributes'] = @attributes unless @attributes.empty?
|
46
|
+
h
|
47
|
+
end
|
48
|
+
|
49
|
+
# Converts the span event into a hash to be used by the MessagePack serialization as a
|
50
|
+
# top-level span field (span.span_events = [event.to_native_format]).
|
51
|
+
# This serialization format removes the serialization limitations of the `span.set_tag('events)` approach,
|
52
|
+
# but is only supported by newer version of the Datadog agent.
|
53
|
+
def to_native_format
|
54
|
+
h = { 'name' => @name, 'time_unix_nano' => @time_unix_nano }
|
55
|
+
|
56
|
+
attr = {}
|
57
|
+
@attributes.each do |key, value|
|
58
|
+
attr[key] = if value.is_a?(Array)
|
59
|
+
{ type: ARRAY_TYPE, array_value: value.map { |v| serialize_native_attribute(v) } }
|
60
|
+
else
|
61
|
+
serialize_native_attribute(value)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
h['attributes'] = attr unless @attributes.empty?
|
66
|
+
|
37
67
|
h
|
38
68
|
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
MIN_INT64_SIGNED = -2**63
|
73
|
+
MAX_INT64_SIGNED = 2 << 63 - 1
|
74
|
+
|
75
|
+
# Checks the attributes hash to ensure it only contains serializable values.
|
76
|
+
# Invalid values are removed from the hash.
|
77
|
+
def validate_attributes!(attributes)
|
78
|
+
attributes.select! do |key, value|
|
79
|
+
case value
|
80
|
+
when Array
|
81
|
+
next true if value.empty?
|
82
|
+
|
83
|
+
first = value.first
|
84
|
+
case first
|
85
|
+
when String, Integer, Float
|
86
|
+
first_type = first.class
|
87
|
+
if value.all? { |v| v.is_a?(first_type) }
|
88
|
+
value.all? { |v| validate_scalar_attribute!(key, v) }
|
89
|
+
else
|
90
|
+
Datadog.logger.warn("Attribute #{key} array must be homogenous: #{value}.")
|
91
|
+
false
|
92
|
+
end
|
93
|
+
when TrueClass, FalseClass
|
94
|
+
if value.all? { |v| v.is_a?(TrueClass) || v.is_a?(FalseClass) }
|
95
|
+
value.all? { |v| validate_scalar_attribute!(key, v) }
|
96
|
+
else
|
97
|
+
Datadog.logger.warn("Attribute #{key} array must be homogenous: #{value}.")
|
98
|
+
false
|
99
|
+
end
|
100
|
+
else
|
101
|
+
Datadog.logger.warn("Attribute #{key} must be a string, number, or boolean: #{value}.")
|
102
|
+
false
|
103
|
+
end
|
104
|
+
when String, Numeric, TrueClass, FalseClass
|
105
|
+
validate_scalar_attribute!(key, value)
|
106
|
+
else
|
107
|
+
Datadog.logger.warn("Attribute #{key} must be a string, number, boolean, or array: #{value}.")
|
108
|
+
false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def validate_scalar_attribute!(key, value)
|
114
|
+
case value
|
115
|
+
when String, TrueClass, FalseClass
|
116
|
+
true
|
117
|
+
when Integer
|
118
|
+
# Cannot be larger than signed 64-bit integer
|
119
|
+
if value < MIN_INT64_SIGNED || value > MAX_INT64_SIGNED
|
120
|
+
Datadog.logger.warn("Attribute #{key} must be within the range of a signed 64-bit integer: #{value}.")
|
121
|
+
false
|
122
|
+
else
|
123
|
+
true
|
124
|
+
end
|
125
|
+
when Float
|
126
|
+
# Has to be finite
|
127
|
+
return true if value.finite?
|
128
|
+
|
129
|
+
Datadog.logger.warn("Attribute #{key} must be a finite number: #{value}.")
|
130
|
+
false
|
131
|
+
else
|
132
|
+
Datadog.logger.warn("Attribute #{key} must be a string, number, or boolean: #{value}.")
|
133
|
+
false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
STRING_TYPE = 0
|
138
|
+
BOOLEAN_TYPE = 1
|
139
|
+
INTEGER_TYPE = 2
|
140
|
+
DOUBLE_TYPE = 3
|
141
|
+
ARRAY_TYPE = 4
|
142
|
+
|
143
|
+
# Serializes individual scalar attributes into the native format.
|
144
|
+
def serialize_native_attribute(value)
|
145
|
+
case value
|
146
|
+
when String
|
147
|
+
{ type: STRING_TYPE, string_value: value }
|
148
|
+
when TrueClass, FalseClass
|
149
|
+
{ type: BOOLEAN_TYPE, bool_value: value }
|
150
|
+
when Integer
|
151
|
+
{ type: INTEGER_TYPE, int_value: value }
|
152
|
+
when Float
|
153
|
+
{ type: DOUBLE_TYPE, double_value: value }
|
154
|
+
else
|
155
|
+
# This is technically unreachable due to the validation in #initialize.
|
156
|
+
raise ArgumentError, "Attribute must be a string, number, or boolean: #{value}."
|
157
|
+
end
|
158
|
+
end
|
39
159
|
end
|
40
160
|
end
|
41
161
|
end
|