datadog 2.39.0 → 2.47.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 +269 -44
- data/README.md +3 -0
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +12 -24
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +256 -193
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -5
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +0 -2
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +19 -20
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +5 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +267 -171
- data/ext/datadog_profiling_native_extension/collectors_stack.h +17 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +307 -217
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -5
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +5 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +19 -11
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +7 -10
- data/ext/datadog_profiling_native_extension/extconf.rb +67 -99
- data/ext/datadog_profiling_native_extension/heap_recorder.c +353 -257
- data/ext/datadog_profiling_native_extension/heap_recorder.h +50 -31
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -27
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +853 -496
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +42 -15
- data/ext/datadog_profiling_native_extension/profiling.c +30 -23
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +4 -80
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -7
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +0 -2
- data/ext/datadog_profiling_native_extension/stack_recorder.c +116 -89
- data/ext/datadog_profiling_native_extension/stack_recorder.h +12 -5
- data/ext/datadog_profiling_native_extension/time_helpers.c +2 -4
- data/ext/datadog_profiling_native_extension/time_helpers.h +15 -15
- data/ext/libdatadog_api/datadog_ruby_common.c +19 -11
- data/ext/libdatadog_api/datadog_ruby_common.h +7 -10
- data/ext/libdatadog_api/di.c +43 -3
- data/ext/libdatadog_api/extconf.rb +6 -1
- data/ext/libdatadog_api/feature_flags.c +8 -0
- data/ext/libdatadog_api/init.c +9 -1
- data/ext/libdatadog_api/otel_thread_context.c +274 -0
- data/ext/libdatadog_api/otel_thread_context.h +5 -0
- data/ext/libdatadog_api/process_discovery.c +15 -1
- data/ext/libdatadog_api/trace_exporter.c +2078 -0
- data/ext/libdatadog_api/trace_exporter.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +14 -9
- data/lib/datadog/ai_guard/component.rb +17 -8
- data/lib/datadog/ai_guard/configuration/ext.rb +2 -0
- data/lib/datadog/ai_guard/configuration.rb +13 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +48 -55
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +1 -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 +12 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -7
- data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +6 -6
- data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +8 -64
- data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +11 -18
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +15 -2
- data/lib/datadog/ai_guard/evaluation.rb +36 -14
- data/lib/datadog/ai_guard/ext.rb +4 -1
- data/lib/datadog/ai_guard/{api_client.rb → http_client.rb} +7 -5
- 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 +58 -57
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +21 -42
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +1 -1
- data/lib/datadog/appsec/assets/blocked.html +1 -108
- data/lib/datadog/appsec/configuration.rb +11 -2
- data/lib/datadog/appsec/context.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +1 -1
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +2 -2
- data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +2 -2
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +2 -2
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/ext.rb +2 -2
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +6 -3
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +30 -3
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +8 -7
- data/lib/datadog/appsec/contrib/rails/request_middleware.rb +2 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +15 -3
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +8 -7
- data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +2 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +12 -12
- data/lib/datadog/appsec/response.rb +1 -1
- data/lib/datadog/appsec/route_normalizer/route_pattern.rb +3 -3
- data/lib/datadog/appsec/security_engine/engine.rb +5 -4
- data/lib/datadog/core/configuration/components.rb +50 -19
- data/lib/datadog/core/configuration/components_state.rb +8 -1
- data/lib/datadog/core/configuration/option_definition.rb +1 -1
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +38 -43
- data/lib/datadog/core/configuration/supported_configurations.rb +18 -2
- data/lib/datadog/core/crashtracking/component.rb +5 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +36 -1
- data/lib/datadog/core/environment/gc.rb +1 -1
- data/lib/datadog/core/environment/vm_cache.rb +1 -1
- data/lib/datadog/core/environment/yjit.rb +2 -2
- data/lib/datadog/core/metrics/helpers.rb +1 -1
- data/lib/datadog/core/metrics/options.rb +2 -2
- data/lib/datadog/core/process_discovery.rb +6 -2
- data/lib/datadog/core/remote/client/capabilities.rb +32 -21
- data/lib/datadog/core/remote/client.rb +45 -4
- data/lib/datadog/core/remote/component.rb +30 -7
- data/lib/datadog/core/remote/configuration/repository.rb +2 -2
- data/lib/datadog/core/remote/dispatcher.rb +47 -6
- data/lib/datadog/core/remote/worker.rb +8 -0
- data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -1
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +1 -1
- data/lib/datadog/core/telemetry/event/app_started.rb +5 -24
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +1 -1
- data/lib/datadog/core/telemetry/event/log.rb +2 -2
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +1 -1
- data/lib/datadog/core/telemetry/metric.rb +2 -2
- data/lib/datadog/core/telemetry/request.rb +2 -2
- data/lib/datadog/core/transport/http.rb +1 -1
- data/lib/datadog/core/transport/transport.rb +1 -1
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +170 -18
- data/lib/datadog/core/utils/sequence.rb +3 -6
- data/lib/datadog/core/utils/time.rb +16 -54
- data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
- data/lib/datadog/data_streams/pathway_context.rb +20 -22
- data/lib/datadog/data_streams/processor.rb +45 -14
- data/lib/datadog/di/boot.rb +1 -0
- data/lib/datadog/di/capture_expression_evaluator/result.rb +30 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +39 -9
- data/lib/datadog/di/component.rb +108 -3
- data/lib/datadog/di/configuration.rb +53 -2
- data/lib/datadog/di/context.rb +7 -2
- data/lib/datadog/di/contrib/active_record.rb +8 -2
- data/lib/datadog/di/el/compiler.rb +88 -12
- data/lib/datadog/di/el/evaluator.rb +82 -2
- data/lib/datadog/di/el/expression.rb +13 -2
- data/lib/datadog/di/evaluation_failure.rb +28 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +87 -0
- data/lib/datadog/di/guardrails_telemetry.rb +203 -0
- data/lib/datadog/di/instrumenter.rb +106 -15
- data/lib/datadog/di/logger.rb +32 -10
- data/lib/datadog/di/probe.rb +9 -1
- data/lib/datadog/di/probe_builder.rb +7 -6
- data/lib/datadog/di/probe_manager.rb +56 -8
- data/lib/datadog/di/probe_notification_builder.rb +31 -28
- data/lib/datadog/di/probe_notifier_worker.rb +56 -6
- data/lib/datadog/di/proc_responder.rb +1 -1
- data/lib/datadog/di/remote.rb +49 -5
- data/lib/datadog/di/serializer.rb +172 -55
- data/lib/datadog/di/snapshot_event.rb +38 -0
- data/lib/datadog/di/transport/http.rb +13 -3
- data/lib/datadog/di/transport/input.rb +32 -7
- data/lib/datadog/error_tracking/component.rb +1 -1
- data/lib/datadog/kit/appsec/events/v2.rb +2 -2
- data/lib/datadog/open_feature/activation.rb +268 -0
- 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 +85 -13
- 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 +124 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +29 -3
- data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
- data/lib/datadog/open_feature/exposures/event.rb +15 -8
- data/lib/datadog/open_feature/ext.rb +19 -0
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +236 -80
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +179 -68
- data/lib/datadog/open_feature/hooks/evaluation_telemetry_opt_out_hook.rb +25 -0
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +24 -21
- data/lib/datadog/open_feature/native_evaluator.rb +20 -6
- data/lib/datadog/open_feature/noop_evaluator.rb +5 -0
- data/lib/datadog/open_feature/provider.rb +315 -10
- data/lib/datadog/open_feature/remote.rb +5 -5
- data/lib/datadog/open_feature/transport.rb +5 -0
- data/lib/datadog/open_feature.rb +31 -1
- data/lib/datadog/opentelemetry/sdk/propagator.rb +1 -1
- data/lib/datadog/opentelemetry/signal_configuration.rb +13 -9
- data/lib/datadog/opentelemetry/trace.rb +3 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +10 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +5 -7
- data/lib/datadog/profiling/collectors/info.rb +40 -13
- data/lib/datadog/profiling/collectors/thread_context.rb +6 -17
- data/lib/datadog/profiling/component.rb +33 -39
- data/lib/datadog/profiling/exporter.rb +10 -10
- data/lib/datadog/profiling/tasks/exec.rb +1 -1
- data/lib/datadog/profiling.rb +4 -0
- data/lib/datadog/symbol_database/extractor.rb +89 -107
- data/lib/datadog/tracing/component.rb +44 -2
- data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +5 -3
- data/lib/datadog/tracing/configuration/ext.rb +4 -0
- data/lib/datadog/tracing/configuration/settings.rb +36 -0
- data/lib/datadog/tracing/context.rb +24 -2
- data/lib/datadog/tracing/context_provider.rb +17 -5
- data/lib/datadog/tracing/contrib/action_cable/events.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/events.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/action_view/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/services.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +10 -5
- data/lib/datadog/tracing/contrib/excon/middleware.rb +10 -3
- data/lib/datadog/tracing/contrib/ext.rb +3 -3
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +10 -4
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +32 -5
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +2 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +16 -1
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +8 -2
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +10 -4
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +4 -0
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +7 -2
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +7 -2
- data/lib/datadog/tracing/contrib/kafka/events.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/patchable.rb +1 -1
- data/lib/datadog/tracing/contrib/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/quantize.rb +36 -2
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +9 -3
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +10 -3
- data/lib/datadog/tracing/contrib/sequel/database.rb +1 -5
- data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
- data/lib/datadog/tracing/contrib/sequel/utils.rb +50 -63
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/utils/quantization/hash_formatter.rb +1 -1
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +108 -3
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/correlation.rb +2 -2
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -2
- data/lib/datadog/tracing/distributed/baggage.rb +1 -3
- data/lib/datadog/tracing/distributed/datadog.rb +3 -3
- data/lib/datadog/tracing/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/distributed/propagation_policy.rb +5 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +14 -271
- 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/metadata/ext.rb +3 -0
- data/lib/datadog/tracing/metadata/tagging.rb +1 -1
- data/lib/datadog/tracing/otel_thread_context.rb +97 -0
- data/lib/datadog/tracing/remote.rb +236 -37
- data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
- data/lib/datadog/tracing/span.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/sync_writer.rb +8 -3
- data/lib/datadog/tracing/trace_digest.rb +22 -4
- data/lib/datadog/tracing/trace_operation.rb +22 -10
- data/lib/datadog/tracing/tracer.rb +28 -7
- data/lib/datadog/tracing/transport/http/telemetry.rb +94 -0
- data/lib/datadog/tracing/transport/http/traces.rb +2 -0
- data/lib/datadog/tracing/transport/io/traces.rb +1 -1
- data/lib/datadog/tracing/transport/native/response.rb +71 -0
- data/lib/datadog/tracing/transport/native/telemetry.rb +17 -0
- data/lib/datadog/tracing/transport/native.rb +395 -0
- data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
- data/lib/datadog/tracing/transport/telemetry.rb +62 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +14 -4
- data/lib/datadog/tracing/transport/traces.rb +85 -38
- data/lib/datadog/tracing/writer.rb +17 -4
- data/lib/datadog/version.rb +1 -1
- metadata +51 -13
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +0 -31
- data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -69
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../core/rate_limiter"
|
|
3
4
|
require_relative "../core/utils/time"
|
|
4
5
|
require_relative "../ruby_version"
|
|
5
6
|
require_relative "fatal_exceptions"
|
|
6
|
-
require_relative "
|
|
7
|
+
require_relative "guardrails_telemetry"
|
|
7
8
|
|
|
8
9
|
# rubocop:disable Lint/AssignmentInCondition
|
|
9
10
|
# rubocop:disable Style/AndOr
|
|
@@ -69,12 +70,35 @@ module Datadog
|
|
|
69
70
|
#
|
|
70
71
|
# @api private
|
|
71
72
|
class Instrumenter
|
|
72
|
-
|
|
73
|
+
# Maximum number of capturing-probe snapshots admitted per second across the
|
|
74
|
+
# whole process.
|
|
75
|
+
GLOBAL_SNAPSHOT_RATE_LIMIT = 20
|
|
76
|
+
|
|
77
|
+
# Maximum number of non-capturing probe emissions admitted per second across
|
|
78
|
+
# the whole process.
|
|
79
|
+
GLOBAL_LOG_RATE_LIMIT = 5000
|
|
80
|
+
|
|
81
|
+
# Initializes the instrumenter.
|
|
82
|
+
#
|
|
83
|
+
# @param settings [Datadog::Core::Configuration::Settings] tracer settings
|
|
84
|
+
# @param serializer [Serializer] serializer for captured values
|
|
85
|
+
# @param logger [DI::Logger] logger for instrumenter diagnostics
|
|
86
|
+
# @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical rate-limit skip metric
|
|
87
|
+
# @param capture_expression_evaluator [CaptureExpressionEvaluator] evaluator for the probe's capture expressions
|
|
88
|
+
# @param code_tracker [CodeTracker, nil] code tracker for line probe installation
|
|
89
|
+
# @param telemetry [Datadog::Core::Telemetry::Component, nil] component instrumenter errors are reported through
|
|
90
|
+
# @return [void]
|
|
91
|
+
def initialize(settings, serializer, logger, guardrails_telemetry:, capture_expression_evaluator:,
|
|
92
|
+
code_tracker: nil, telemetry: nil)
|
|
73
93
|
@settings = settings
|
|
74
94
|
@serializer = serializer
|
|
75
95
|
@logger = logger
|
|
76
96
|
@telemetry = telemetry
|
|
97
|
+
@guardrails_telemetry = guardrails_telemetry
|
|
98
|
+
@capture_expression_evaluator = capture_expression_evaluator
|
|
77
99
|
@code_tracker = code_tracker
|
|
100
|
+
@global_snapshot_rate_limiter = Datadog::Core::TokenBucket.new(GLOBAL_SNAPSHOT_RATE_LIMIT)
|
|
101
|
+
@global_log_rate_limiter = Datadog::Core::TokenBucket.new(GLOBAL_LOG_RATE_LIMIT)
|
|
78
102
|
|
|
79
103
|
@lock = Mutex.new
|
|
80
104
|
end
|
|
@@ -83,6 +107,12 @@ module Datadog
|
|
|
83
107
|
attr_reader :serializer
|
|
84
108
|
attr_reader :logger
|
|
85
109
|
attr_reader :telemetry
|
|
110
|
+
# The guardrails metric emitter.
|
|
111
|
+
# @return [GuardrailsTelemetry]
|
|
112
|
+
attr_reader :guardrails_telemetry
|
|
113
|
+
# The capture expression evaluator.
|
|
114
|
+
# @return [CaptureExpressionEvaluator]
|
|
115
|
+
attr_reader :capture_expression_evaluator
|
|
86
116
|
attr_reader :code_tracker
|
|
87
117
|
|
|
88
118
|
# The code tracker is a global singleton created lazily by
|
|
@@ -91,10 +121,41 @@ module Datadog
|
|
|
91
121
|
# Component#start! assigns the now-current tracker here.
|
|
92
122
|
attr_writer :code_tracker
|
|
93
123
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
124
|
+
# Process-wide snapshot rate limiter.
|
|
125
|
+
# @return [Datadog::Core::TokenBucket]
|
|
126
|
+
attr_reader :global_snapshot_rate_limiter
|
|
127
|
+
# Process-wide log rate limiter.
|
|
128
|
+
# @return [Datadog::Core::TokenBucket]
|
|
129
|
+
attr_reader :global_log_rate_limiter
|
|
130
|
+
|
|
131
|
+
# Returns the process-wide rate limiter for the probe.
|
|
132
|
+
#
|
|
133
|
+
# @param probe [Probe] the probe whose invocation is being rate limited
|
|
134
|
+
# @return [Datadog::Core::TokenBucket] the shared limiter for the probe's category
|
|
135
|
+
def probe_global_rate_limiter(probe)
|
|
136
|
+
if probe.capturing?
|
|
137
|
+
global_snapshot_rate_limiter
|
|
138
|
+
else
|
|
139
|
+
global_log_rate_limiter
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Emits the canonical rate-limit skip metric for a probe.
|
|
144
|
+
#
|
|
145
|
+
# @param probe [Probe] the probe being skipped
|
|
146
|
+
# @param reason [String] a GuardrailsTelemetry::Reason constant for the rejecting limit
|
|
147
|
+
# @return [void]
|
|
148
|
+
def record_rate_limit_skip(reason, probe)
|
|
149
|
+
logger.trace do
|
|
150
|
+
"di: #{probe.type} probe #{probe.id}: skipping due to " \
|
|
151
|
+
"#{(reason == GuardrailsTelemetry::Reason::RATE_LIMIT_PROBE) ? "per-probe" : "global"} rate limit" \
|
|
152
|
+
" (#{reason})"
|
|
153
|
+
end
|
|
154
|
+
guardrails_telemetry.skipped(
|
|
155
|
+
reason: reason,
|
|
156
|
+
probe: probe,
|
|
97
157
|
)
|
|
158
|
+
nil
|
|
98
159
|
end
|
|
99
160
|
|
|
100
161
|
# This is a substitute for Thread::Backtrace::Location
|
|
@@ -160,6 +221,7 @@ module Datadog
|
|
|
160
221
|
end
|
|
161
222
|
|
|
162
223
|
loc = target_method&.source_location
|
|
224
|
+
# @type var instrumenter: Instrumenter
|
|
163
225
|
instrumenter = self
|
|
164
226
|
|
|
165
227
|
mod = Module.new do
|
|
@@ -193,7 +255,7 @@ module Datadog
|
|
|
193
255
|
# user probe on Proc#call cannot intercept the trampoline, and no
|
|
194
256
|
# Proc is allocated for the block.
|
|
195
257
|
if RubyVersion.is?(">= 3")
|
|
196
|
-
define_method(method_name) do |*args, **kwargs, &target_block|
|
|
258
|
+
define_method(method_name) do |*args, **kwargs, &target_block|
|
|
197
259
|
# steep:ignore FallbackAny below: Steep cannot narrow the
|
|
198
260
|
# **kwargs parameter inside this define_method block, so it
|
|
199
261
|
# falls back to untyped at the super and run_method_probe sites.
|
|
@@ -211,7 +273,7 @@ module Datadog
|
|
|
211
273
|
end
|
|
212
274
|
end
|
|
213
275
|
else
|
|
214
|
-
define_method(method_name) do |*args, &target_block|
|
|
276
|
+
define_method(method_name) do |*args, &target_block|
|
|
215
277
|
if DI.in_probe?
|
|
216
278
|
return super(*args, &target_block)
|
|
217
279
|
end
|
|
@@ -230,7 +292,7 @@ module Datadog
|
|
|
230
292
|
super(*args, &target_block)
|
|
231
293
|
end
|
|
232
294
|
end
|
|
233
|
-
ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
|
|
295
|
+
ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
|
|
234
296
|
end
|
|
235
297
|
end
|
|
236
298
|
|
|
@@ -461,7 +523,7 @@ module Datadog
|
|
|
461
523
|
# @param args [Array] positional arguments passed to the probed method
|
|
462
524
|
# @param kwargs [Hash{Symbol => Object}] keyword arguments passed to the probed method
|
|
463
525
|
# @param target_block [Proc, nil] block argument passed to the probed method
|
|
464
|
-
# @param target_self [
|
|
526
|
+
# @param target_self [any] the receiver of the probed method invocation
|
|
465
527
|
# @param probe [Datadog::DI::Probe] the probe whose callback this invocation runs
|
|
466
528
|
# @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback] callback target invoked with the built Context
|
|
467
529
|
# @param loc [Array(String, Integer), nil] source location of the probed method, or nil for virtual/lazily-defined methods
|
|
@@ -507,7 +569,7 @@ module Datadog
|
|
|
507
569
|
# the context, we won't be able to report anything as
|
|
508
570
|
# the probe notifier builder requires a context.
|
|
509
571
|
begin
|
|
510
|
-
responder.probe_condition_evaluation_failed_callback(context, exc)
|
|
572
|
+
responder.probe_condition_evaluation_failed_callback(context, condition, exc)
|
|
511
573
|
rescue Exception => nested_exc # standard:disable Lint/RescueException
|
|
512
574
|
Datadog::DI.reraise_if_fatal(nested_exc)
|
|
513
575
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
@@ -528,12 +590,22 @@ module Datadog
|
|
|
528
590
|
end
|
|
529
591
|
|
|
530
592
|
rate_limiter = probe.rate_limiter
|
|
531
|
-
|
|
593
|
+
admitted = continue
|
|
594
|
+
if continue && rate_limiter && !rate_limiter.allow?
|
|
595
|
+
admitted = false
|
|
596
|
+
record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_PROBE, probe)
|
|
597
|
+
end
|
|
598
|
+
if admitted && !probe_global_rate_limiter(probe).allow?
|
|
599
|
+
admitted = false
|
|
600
|
+
record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL, probe)
|
|
601
|
+
end
|
|
602
|
+
if admitted
|
|
532
603
|
# Arguments may be mutated by the method, therefore
|
|
533
604
|
# they need to be serialized prior to method invocation.
|
|
534
605
|
serialized_entry_args = if probe.capture_snapshot?
|
|
535
606
|
serializer.serialize_args(args, kwargs, target_self,
|
|
536
|
-
|
|
607
|
+
deadline: serializer.serialization_deadline,
|
|
608
|
+
**probe.snapshot_serializer_limits(settings),)
|
|
537
609
|
end
|
|
538
610
|
|
|
539
611
|
entry_capture_expressions = nil
|
|
@@ -545,8 +617,9 @@ module Datadog
|
|
|
545
617
|
target_self: target_self,
|
|
546
618
|
locals: serializer.combine_args(args, kwargs, target_self),
|
|
547
619
|
)
|
|
548
|
-
|
|
549
|
-
|
|
620
|
+
entry_capture_result = capture_expression_evaluator.evaluate(probe, entry_context)
|
|
621
|
+
entry_capture_expressions = entry_capture_result.serialized_values
|
|
622
|
+
entry_capture_evaluation_errors = entry_capture_result.errors
|
|
550
623
|
rescue Exception => exc # standard:disable Lint/RescueException
|
|
551
624
|
Datadog::DI.reraise_if_fatal(exc)
|
|
552
625
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
@@ -715,6 +788,13 @@ module Datadog
|
|
|
715
788
|
public :kwargs_from_splat
|
|
716
789
|
end
|
|
717
790
|
|
|
791
|
+
# Trace point callback for a line probe.
|
|
792
|
+
#
|
|
793
|
+
# @param probe [Probe] the probe installed on this line
|
|
794
|
+
# @param iseq [RubyVM::InstructionSequence, nil] instruction sequence the trace point is targeted at, or nil when untargeted
|
|
795
|
+
# @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback] callback target invoked with the built Context
|
|
796
|
+
# @param tp [TracePoint] the firing trace point
|
|
797
|
+
# @return [void]
|
|
718
798
|
def line_trace_point_callback(probe, iseq, responder, tp)
|
|
719
799
|
di_start_time = Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
|
|
720
800
|
|
|
@@ -791,7 +871,15 @@ module Datadog
|
|
|
791
871
|
|
|
792
872
|
# In practice we should always have a rate limiter, but be safe
|
|
793
873
|
# and check that it is in fact set.
|
|
794
|
-
|
|
874
|
+
if probe.rate_limiter && !probe.rate_limiter.allow?
|
|
875
|
+
record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_PROBE, probe)
|
|
876
|
+
return
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
unless probe_global_rate_limiter(probe).allow?
|
|
880
|
+
record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL, probe)
|
|
881
|
+
return
|
|
882
|
+
end
|
|
795
883
|
|
|
796
884
|
# The context creation is relatively expensive and we don't
|
|
797
885
|
# want to run it if the callback won't be executed due to the
|
|
@@ -802,12 +890,14 @@ module Datadog
|
|
|
802
890
|
responder.probe_executed_callback(context)
|
|
803
891
|
|
|
804
892
|
check_and_disable_if_exceeded(probe, responder, di_start_time)
|
|
893
|
+
nil
|
|
805
894
|
rescue Exception => exc # standard:disable Lint/RescueException
|
|
806
895
|
Datadog::DI.reraise_if_fatal(exc)
|
|
807
896
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
808
897
|
logger.debug { "di: unhandled exception in line trace point: #{exc.class}: #{exc.message}" }
|
|
809
898
|
telemetry&.report(exc, description: "Unhandled exception in line trace point")
|
|
810
899
|
# TODO test this path
|
|
900
|
+
nil
|
|
811
901
|
end
|
|
812
902
|
|
|
813
903
|
def build_trace_point_context(probe, tp)
|
|
@@ -840,6 +930,7 @@ module Datadog
|
|
|
840
930
|
# avoid a dependency on ProbeManager from Instrumenter.
|
|
841
931
|
probe.disable!
|
|
842
932
|
responder.probe_disabled_callback(probe, di_duration)
|
|
933
|
+
nil
|
|
843
934
|
end
|
|
844
935
|
end
|
|
845
936
|
|
data/lib/datadog/di/logger.rb
CHANGED
|
@@ -1,29 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "forwardable"
|
|
4
|
-
|
|
5
3
|
module Datadog
|
|
6
4
|
module DI
|
|
7
5
|
# Logger facade to add the +trace+ method.
|
|
8
6
|
#
|
|
9
7
|
# @api private
|
|
10
8
|
class Logger
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
# Initializes the logger facade with the trace-logging gate resolved
|
|
10
|
+
# once.
|
|
11
|
+
# Resolving the gate at construction keeps the per-call settings
|
|
12
|
+
# traversal off the probe hot path. Components are rebuilt on
|
|
13
|
+
# reconfiguration, so the cached value tracks configuration
|
|
14
|
+
# changes.
|
|
15
|
+
#
|
|
16
|
+
# @param settings [Datadog::Core::Configuration::Settings] tracer settings the gate is resolved from
|
|
17
|
+
# @param target [::Logger] logger the facade delegates to
|
|
13
18
|
def initialize(settings, target)
|
|
14
|
-
@
|
|
19
|
+
@trace_logging = settings.dynamic_instrumentation.internal.trace_logging
|
|
15
20
|
@target = target
|
|
16
21
|
end
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
# Whether trace logging is enabled.
|
|
24
|
+
# @return [Boolean]
|
|
25
|
+
attr_reader :trace_logging
|
|
26
|
+
# The target logger.
|
|
27
|
+
# @return [::Logger]
|
|
19
28
|
attr_reader :target
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
# Writes the given message or the block's message to the target
|
|
31
|
+
# logger.
|
|
32
|
+
#
|
|
33
|
+
# @param message [String, nil] message written when no block is given
|
|
34
|
+
# @return [void]
|
|
35
|
+
def debug(message = nil, &block)
|
|
36
|
+
target.debug(message, &block)
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
# Writes the block's message to the target logger at debug level when
|
|
41
|
+
# the trace-logging gate resolved at construction is enabled.
|
|
42
|
+
#
|
|
43
|
+
# @return [void]
|
|
44
|
+
def trace
|
|
45
|
+
if trace_logging
|
|
46
|
+
debug { yield }
|
|
26
47
|
end
|
|
48
|
+
nil
|
|
27
49
|
end
|
|
28
50
|
end
|
|
29
51
|
end
|
data/lib/datadog/di/probe.rb
CHANGED
|
@@ -97,7 +97,7 @@ module Datadog
|
|
|
97
97
|
@evaluate_at = evaluate_at
|
|
98
98
|
@condition = condition
|
|
99
99
|
|
|
100
|
-
@rate_limit = rate_limit || (
|
|
100
|
+
@rate_limit = rate_limit || (capturing? ? 1 : 5000)
|
|
101
101
|
@rate_limiter = Datadog::Core::TokenBucket.new(@rate_limit)
|
|
102
102
|
|
|
103
103
|
# At most one report per second.
|
|
@@ -166,6 +166,14 @@ module Datadog
|
|
|
166
166
|
!@capture_expressions.empty?
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
# Whether this probe captures user data, either as a full snapshot
|
|
170
|
+
# or via capture expressions.
|
|
171
|
+
#
|
|
172
|
+
# @return [Boolean]
|
|
173
|
+
def capturing?
|
|
174
|
+
capture_snapshot? || capture_expressions?
|
|
175
|
+
end
|
|
176
|
+
|
|
169
177
|
def evaluate_at_entry?
|
|
170
178
|
evaluate_at == :entry
|
|
171
179
|
end
|
|
@@ -45,8 +45,8 @@ module Datadog
|
|
|
45
45
|
unless cond_spec["dsl"] && cond_spec["json"]
|
|
46
46
|
raise ArgumentError, "Malformed condition specification for probe: #{config}"
|
|
47
47
|
end
|
|
48
|
-
compiled = EL::Compiler.new.compile(cond_spec["json"])
|
|
49
|
-
EL::Expression.new(cond_spec["dsl"], compiled)
|
|
48
|
+
compiled, regexps = EL::Compiler.new.compile(cond_spec["json"])
|
|
49
|
+
EL::Expression.new(cond_spec["dsl"], compiled, regexps: regexps)
|
|
50
50
|
end
|
|
51
51
|
capture_expressions = build_capture_expressions(config["captureExpressions"])
|
|
52
52
|
capture_expressions = dedup_capture_expressions(capture_expressions, config["id"], logger)
|
|
@@ -100,8 +100,8 @@ module Datadog
|
|
|
100
100
|
unless Hash === expr_spec && expr_spec["dsl"] && expr_spec["json"]
|
|
101
101
|
raise ArgumentError, "captureExpressions entry #{name}: missing or malformed expr"
|
|
102
102
|
end
|
|
103
|
-
compiled = EL::Compiler.new.compile(expr_spec["json"])
|
|
104
|
-
expr = EL::Expression.new(expr_spec["dsl"], compiled)
|
|
103
|
+
compiled, regexps = EL::Compiler.new.compile(expr_spec["json"])
|
|
104
|
+
expr = EL::Expression.new(expr_spec["dsl"], compiled, regexps: regexps)
|
|
105
105
|
limits = build_capture_limits(entry["capture"])
|
|
106
106
|
CaptureExpression.new(name: name, expr: expr, limits: limits)
|
|
107
107
|
end
|
|
@@ -152,8 +152,9 @@ module Datadog
|
|
|
152
152
|
unless dsl = segment["dsl"]
|
|
153
153
|
raise ArgumentError, "Missing dsl for json in segment: #{segment}"
|
|
154
154
|
end
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
compiler = EL::Compiler.new
|
|
156
|
+
compiled, regexps = compiler.compile(ast)
|
|
157
|
+
EL::Expression.new(dsl, compiled, regexps: regexps, redaction_identifier: compiler.redaction_identifier(ast))
|
|
157
158
|
else
|
|
158
159
|
# TODO report to telemetry?
|
|
159
160
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# rubocop:disable Lint/AssignmentInCondition
|
|
4
4
|
|
|
5
5
|
require_relative "fatal_exceptions"
|
|
6
|
+
require_relative "guardrails_telemetry"
|
|
6
7
|
|
|
7
8
|
module Datadog
|
|
8
9
|
module DI
|
|
@@ -18,14 +19,26 @@ module Datadog
|
|
|
18
19
|
#
|
|
19
20
|
# @api private
|
|
20
21
|
class ProbeManager
|
|
22
|
+
# Initializes the probe manager.
|
|
23
|
+
#
|
|
24
|
+
# @param settings [Datadog::Core::Configuration::Settings] tracer settings
|
|
25
|
+
# @param instrumenter [Instrumenter] instrumenter that executes installed probes
|
|
26
|
+
# @param probe_notification_builder [ProbeNotificationBuilder] builder for status and snapshot payloads
|
|
27
|
+
# @param probe_notifier_worker [ProbeNotifierWorker] worker that sends the built payloads
|
|
28
|
+
# @param logger [DI::Logger] logger for probe manager diagnostics
|
|
29
|
+
# @param probe_repository [ProbeRepository] repository of installed probes
|
|
30
|
+
# @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical condition-error skip metric
|
|
31
|
+
# @param telemetry [Datadog::Core::Telemetry::Component, nil] component probe manager errors are reported through
|
|
32
|
+
# @return [void]
|
|
21
33
|
def initialize(settings, instrumenter, probe_notification_builder,
|
|
22
|
-
probe_notifier_worker, logger, probe_repository, telemetry: nil)
|
|
34
|
+
probe_notifier_worker, logger, probe_repository, guardrails_telemetry:, telemetry: nil)
|
|
23
35
|
@settings = settings
|
|
24
36
|
@instrumenter = instrumenter
|
|
25
37
|
@probe_notification_builder = probe_notification_builder
|
|
26
38
|
@probe_notifier_worker = probe_notifier_worker
|
|
27
39
|
@logger = logger
|
|
28
40
|
@telemetry = telemetry
|
|
41
|
+
@guardrails_telemetry = guardrails_telemetry
|
|
29
42
|
@probe_repository = probe_repository
|
|
30
43
|
|
|
31
44
|
@definition_trace_point = TracePoint.new(:end) do |tp|
|
|
@@ -40,6 +53,9 @@ module Datadog
|
|
|
40
53
|
|
|
41
54
|
attr_reader :logger
|
|
42
55
|
attr_reader :telemetry
|
|
56
|
+
# The guardrails metric emitter.
|
|
57
|
+
# @return [GuardrailsTelemetry]
|
|
58
|
+
attr_reader :guardrails_telemetry
|
|
43
59
|
attr_reader :probe_repository
|
|
44
60
|
|
|
45
61
|
# Stops the probe manager without permanently releasing resources.
|
|
@@ -303,25 +319,43 @@ module Datadog
|
|
|
303
319
|
end
|
|
304
320
|
|
|
305
321
|
payload = probe_notification_builder.build_executed(context)
|
|
306
|
-
probe_notifier_worker.add_snapshot(payload)
|
|
322
|
+
probe_notifier_worker.add_snapshot(payload, probe: probe)
|
|
307
323
|
end
|
|
308
324
|
|
|
309
325
|
# Callback invoked when a probe's condition expression fails to evaluate.
|
|
310
326
|
#
|
|
311
327
|
# This can happen when the expression references undefined variables,
|
|
312
328
|
# has type mismatches, or encounters runtime errors during evaluation.
|
|
313
|
-
# Rate-limited to 1 notification per second per probe to
|
|
314
|
-
#
|
|
329
|
+
# Rate-limited to 1 notification per second per probe, and subject to
|
|
330
|
+
# the process-wide global snapshot rate limit, to avoid flooding the
|
|
331
|
+
# backend when conditions fail repeatedly.
|
|
315
332
|
#
|
|
316
333
|
# @param context [Context] The execution context containing probe and captured data
|
|
317
|
-
# @param expr [
|
|
334
|
+
# @param expr [EL::Expression] The condition expression that failed
|
|
318
335
|
# @param exc [Exception] The exception raised during condition evaluation
|
|
336
|
+
# @return [void]
|
|
319
337
|
def probe_condition_evaluation_failed_callback(context, expr, exc)
|
|
320
338
|
probe = context.probe
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
339
|
+
rate_limiter = probe.condition_evaluation_failed_rate_limiter
|
|
340
|
+
if rate_limiter&.allow?
|
|
341
|
+
if instrumenter.global_snapshot_rate_limiter.allow?
|
|
342
|
+
payload = probe_notification_builder.build_condition_evaluation_failed(context, expr, exc)
|
|
343
|
+
probe_notifier_worker.add_snapshot(payload, probe: probe)
|
|
344
|
+
else
|
|
345
|
+
logger.trace do
|
|
346
|
+
"di: #{probe.type} probe #{probe.id}: skipping condition error snapshot due to global rate limit" \
|
|
347
|
+
" (#{GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL})"
|
|
348
|
+
end
|
|
349
|
+
record_condition_error_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL, probe)
|
|
350
|
+
end
|
|
351
|
+
elsif rate_limiter
|
|
352
|
+
logger.trace do
|
|
353
|
+
"di: #{probe.type} probe #{probe.id}: skipping condition evaluation failure" \
|
|
354
|
+
" notification due to per-probe rate limit" \
|
|
355
|
+
" (#{GuardrailsTelemetry::Reason::EVALUATION_ERROR_THROTTLED})"
|
|
356
|
+
end
|
|
324
357
|
end
|
|
358
|
+
nil
|
|
325
359
|
end
|
|
326
360
|
|
|
327
361
|
# Callback invoked when a probe is disabled, for example due to
|
|
@@ -336,6 +370,20 @@ module Datadog
|
|
|
336
370
|
probe_notifier_worker.add_status(payload, probe: probe)
|
|
337
371
|
end
|
|
338
372
|
|
|
373
|
+
# Emits the canonical skip metric for a condition evaluation failure
|
|
374
|
+
# notification rejected by a rate limiter.
|
|
375
|
+
#
|
|
376
|
+
# @param probe [Probe] the probe whose condition evaluation failed
|
|
377
|
+
# @param reason [String] the GuardrailsTelemetry::Reason constant for the rejecting limit
|
|
378
|
+
# @return [void]
|
|
379
|
+
def record_condition_error_skip(reason, probe)
|
|
380
|
+
guardrails_telemetry.skipped(
|
|
381
|
+
reason: reason,
|
|
382
|
+
probe: probe,
|
|
383
|
+
)
|
|
384
|
+
nil
|
|
385
|
+
end
|
|
386
|
+
|
|
339
387
|
# Class/module definition trace point (:end type).
|
|
340
388
|
# Used to install hooks when the target classes/modules aren't yet
|
|
341
389
|
# defined when the hook request is received.
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# rubocop:disable Lint/AssignmentInCondition
|
|
4
4
|
|
|
5
|
+
require_relative "evaluation_failure"
|
|
5
6
|
require_relative "fatal_exceptions"
|
|
6
|
-
require_relative "capture_expression_evaluator"
|
|
7
7
|
|
|
8
8
|
module Datadog
|
|
9
9
|
module DI
|
|
@@ -11,14 +11,18 @@ module Datadog
|
|
|
11
11
|
#
|
|
12
12
|
# @api private
|
|
13
13
|
class ProbeNotificationBuilder
|
|
14
|
-
|
|
14
|
+
# Initializes the builder.
|
|
15
|
+
#
|
|
16
|
+
# @param settings [Datadog::Core::Configuration::Settings] tracer settings
|
|
17
|
+
# @param serializer [Serializer] serializer for captured values
|
|
18
|
+
# @param logger [DI::Logger] logger for builder diagnostics
|
|
19
|
+
# @param capture_expression_evaluator [CaptureExpressionEvaluator] evaluator for the probe's capture expressions
|
|
20
|
+
# @return [void]
|
|
21
|
+
def initialize(settings, serializer, logger, capture_expression_evaluator:)
|
|
15
22
|
@settings = settings
|
|
16
23
|
@serializer = serializer
|
|
17
24
|
@logger = logger
|
|
18
|
-
@
|
|
19
|
-
@capture_expression_evaluator = CaptureExpressionEvaluator.new(
|
|
20
|
-
settings: settings, serializer: serializer, logger: logger, telemetry: telemetry,
|
|
21
|
-
)
|
|
25
|
+
@capture_expression_evaluator = capture_expression_evaluator
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
attr_reader :settings
|
|
@@ -27,8 +31,6 @@ module Datadog
|
|
|
27
31
|
|
|
28
32
|
attr_reader :logger
|
|
29
33
|
|
|
30
|
-
attr_reader :telemetry
|
|
31
|
-
|
|
32
34
|
attr_reader :capture_expression_evaluator
|
|
33
35
|
|
|
34
36
|
def build_received(probe)
|
|
@@ -53,7 +55,7 @@ module Datadog
|
|
|
53
55
|
build_status(probe,
|
|
54
56
|
message: "Instrumentation for probe #{probe.id} failed: #{exc}",
|
|
55
57
|
status: "ERROR",
|
|
56
|
-
exception: exc)
|
|
58
|
+
exception: exc,)
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def build_disabled(probe, duration)
|
|
@@ -83,10 +85,11 @@ module Datadog
|
|
|
83
85
|
capture_expression_evaluation_errors = []
|
|
84
86
|
captures = if probe.capture_snapshot?
|
|
85
87
|
snapshot_limits = probe.snapshot_serializer_limits(settings)
|
|
88
|
+
serialization_deadline = serializer.serialization_deadline
|
|
86
89
|
if probe.method?
|
|
87
90
|
return_arguments = {
|
|
88
|
-
"@return": serializer.serialize_value(context.return_value, **snapshot_limits),
|
|
89
|
-
self: serializer.serialize_value(context.target_self, **snapshot_limits),
|
|
91
|
+
"@return": serializer.serialize_value(context.return_value, deadline: serialization_deadline, **snapshot_limits),
|
|
92
|
+
self: serializer.serialize_value(context.target_self, deadline: serialization_deadline, **snapshot_limits),
|
|
90
93
|
}
|
|
91
94
|
{
|
|
92
95
|
entry: {
|
|
@@ -99,10 +102,10 @@ module Datadog
|
|
|
99
102
|
}
|
|
100
103
|
elsif probe.line?
|
|
101
104
|
{
|
|
102
|
-
lines: (locals = context.serialized_locals) && {
|
|
105
|
+
lines: (locals = context.serialized_locals(serialization_deadline: serialization_deadline)) && {
|
|
103
106
|
probe.line_no => {
|
|
104
107
|
locals: locals,
|
|
105
|
-
arguments: {self: serializer.serialize_value(context.target_self, **snapshot_limits)},
|
|
108
|
+
arguments: {self: serializer.serialize_value(context.target_self, deadline: serialization_deadline, **snapshot_limits)},
|
|
106
109
|
},
|
|
107
110
|
},
|
|
108
111
|
}
|
|
@@ -116,8 +119,9 @@ module Datadog
|
|
|
116
119
|
entry: {captureExpressions: captured_block},
|
|
117
120
|
}
|
|
118
121
|
else
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
capture_evaluation_result = capture_expression_evaluator.evaluate(probe, context)
|
|
123
|
+
captured_block = capture_evaluation_result.serialized_values
|
|
124
|
+
capture_expression_evaluation_errors = capture_evaluation_result.errors
|
|
121
125
|
{
|
|
122
126
|
return: {
|
|
123
127
|
captureExpressions: captured_block,
|
|
@@ -126,8 +130,9 @@ module Datadog
|
|
|
126
130
|
}
|
|
127
131
|
end
|
|
128
132
|
elsif probe.line?
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
capture_evaluation_result = capture_expression_evaluator.evaluate(probe, context)
|
|
134
|
+
captured_block = capture_evaluation_result.serialized_values
|
|
135
|
+
capture_expression_evaluation_errors = capture_evaluation_result.errors
|
|
131
136
|
{
|
|
132
137
|
lines: {
|
|
133
138
|
probe.line_no => {captureExpressions: captured_block},
|
|
@@ -144,14 +149,11 @@ module Datadog
|
|
|
144
149
|
evaluation_errors.concat(capture_expression_evaluation_errors)
|
|
145
150
|
build_snapshot_base(context,
|
|
146
151
|
evaluation_errors: evaluation_errors, message: message,
|
|
147
|
-
captures: captures)
|
|
152
|
+
captures: captures,)
|
|
148
153
|
end
|
|
149
154
|
|
|
150
155
|
def build_condition_evaluation_failed(context, expression, exception)
|
|
151
|
-
error = {
|
|
152
|
-
message: "#{exception.class}: #{exception}",
|
|
153
|
-
expr: expression.dsl_expr,
|
|
154
|
-
}
|
|
156
|
+
error = EvaluationFailure.new(expr: expression.dsl_expr, message: "#{exception.class}: #{exception}")
|
|
155
157
|
build_snapshot_base(context, evaluation_errors: [error])
|
|
156
158
|
end
|
|
157
159
|
|
|
@@ -179,7 +181,7 @@ module Datadog
|
|
|
179
181
|
if status == "ERROR"
|
|
180
182
|
diagnostics[:exception] = { # steep:ignore
|
|
181
183
|
type: exception ? exception.class.name : "Error",
|
|
182
|
-
message: exception ? exception.message : message
|
|
184
|
+
message: exception ? exception.message : message,
|
|
183
185
|
}
|
|
184
186
|
end
|
|
185
187
|
|
|
@@ -350,7 +352,7 @@ module Datadog
|
|
|
350
352
|
snapshot: {
|
|
351
353
|
id: SecureRandom.uuid,
|
|
352
354
|
timestamp: timestamp,
|
|
353
|
-
evaluationErrors: evaluation_errors,
|
|
355
|
+
evaluationErrors: evaluation_errors.map { |failure| {expr: failure.expr, message: failure.message} },
|
|
354
356
|
probe: {
|
|
355
357
|
id: probe.id,
|
|
356
358
|
version: 0,
|
|
@@ -379,6 +381,7 @@ module Datadog
|
|
|
379
381
|
thread_id: nil,
|
|
380
382
|
version: 2,
|
|
381
383
|
},
|
|
384
|
+
runtime_id: Core::Environment::Identity.id,
|
|
382
385
|
# TODO add tests that the trace/span id is correctly propagated
|
|
383
386
|
"dd.trace_id": active_trace&.id&.to_s,
|
|
384
387
|
"dd.span_id": active_span&.id&.to_s,
|
|
@@ -405,16 +408,16 @@ module Datadog
|
|
|
405
408
|
when String
|
|
406
409
|
segment
|
|
407
410
|
when EL::Expression
|
|
408
|
-
serializer.serialize_value_for_message(segment.evaluate(context))
|
|
411
|
+
serializer.serialize_value_for_message(segment.evaluate(context), name: segment.redaction_identifier)
|
|
409
412
|
else
|
|
410
413
|
raise ArgumentError, "Invalid template segment type: #{segment}"
|
|
411
414
|
end
|
|
412
415
|
rescue Exception => exc # standard:disable Lint/RescueException
|
|
413
416
|
Datadog::DI.reraise_if_fatal(exc)
|
|
414
|
-
evaluation_errors <<
|
|
415
|
-
message: "#{exc.class}: #{exc.message}",
|
|
417
|
+
evaluation_errors << EvaluationFailure.new(
|
|
416
418
|
expr: segment.dsl_expr, # steep:ignore NoMethod
|
|
417
|
-
|
|
419
|
+
message: "#{exc.class}: #{exc.message}",
|
|
420
|
+
)
|
|
418
421
|
"[evaluation error]"
|
|
419
422
|
end.join
|
|
420
423
|
[message, evaluation_errors]
|