datadog 2.20.0 → 2.26.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 +212 -1
- data/README.md +0 -1
- data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +93 -23
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +21 -5
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +9 -4
- data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +1 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
- data/ext/libdatadog_api/ddsketch.c +106 -0
- data/ext/libdatadog_api/feature_flags.c +554 -0
- data/ext/libdatadog_api/feature_flags.h +5 -0
- data/ext/libdatadog_api/init.c +5 -0
- data/ext/libdatadog_api/library_config.c +34 -25
- data/ext/libdatadog_api/process_discovery.c +24 -18
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/api_client.rb +82 -0
- data/lib/datadog/ai_guard/component.rb +42 -0
- data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
- data/lib/datadog/ai_guard/configuration/settings.rb +98 -0
- data/lib/datadog/ai_guard/configuration.rb +11 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +34 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +81 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +43 -0
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
- data/lib/datadog/ai_guard/evaluation.rb +72 -0
- data/lib/datadog/ai_guard/ext.rb +16 -0
- data/lib/datadog/ai_guard.rb +153 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +26 -5
- data/lib/datadog/appsec/api_security/sampler.rb +7 -4
- data/lib/datadog/appsec/assets/blocked.html +8 -0
- data/lib/datadog/appsec/assets/blocked.json +1 -1
- data/lib/datadog/appsec/assets/blocked.text +3 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
- data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
- data/lib/datadog/appsec/assets.rb +1 -1
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/compressed_json.rb +1 -1
- data/lib/datadog/appsec/configuration/settings.rb +9 -0
- data/lib/datadog/appsec/context.rb +2 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
- data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
- data/lib/datadog/appsec/event.rb +12 -14
- data/lib/datadog/appsec/metrics/collector.rb +19 -3
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
- data/lib/datadog/appsec/remote.rb +34 -25
- data/lib/datadog/appsec/response.rb +18 -4
- data/lib/datadog/appsec/security_engine/engine.rb +3 -3
- data/lib/datadog/appsec/security_engine/result.rb +29 -9
- data/lib/datadog/appsec/security_engine/runner.rb +19 -9
- data/lib/datadog/appsec/security_event.rb +5 -7
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -4
- data/lib/datadog/core/configuration/components.rb +59 -11
- data/lib/datadog/core/configuration/config_helper.rb +100 -0
- data/lib/datadog/core/configuration/deprecations.rb +36 -0
- data/lib/datadog/core/configuration/ext.rb +0 -1
- data/lib/datadog/core/configuration/option.rb +38 -43
- data/lib/datadog/core/configuration/option_definition.rb +4 -11
- data/lib/datadog/core/configuration/options.rb +9 -10
- data/lib/datadog/core/configuration/settings.rb +38 -9
- data/lib/datadog/core/configuration/stable_config.rb +10 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +373 -0
- data/lib/datadog/core/configuration.rb +2 -2
- data/lib/datadog/core/ddsketch.rb +19 -0
- data/lib/datadog/core/deprecations.rb +2 -2
- data/lib/datadog/core/environment/cgroup.rb +52 -25
- data/lib/datadog/core/environment/container.rb +140 -46
- data/lib/datadog/core/environment/ext.rb +7 -2
- data/lib/datadog/core/environment/git.rb +2 -2
- data/lib/datadog/core/environment/process.rb +87 -0
- data/lib/datadog/core/environment/variable_helpers.rb +3 -3
- data/lib/datadog/core/environment/yjit.rb +2 -1
- data/lib/datadog/core/error.rb +6 -6
- data/lib/datadog/core/feature_flags.rb +61 -0
- data/lib/datadog/core/metrics/client.rb +2 -2
- data/lib/datadog/core/pin.rb +8 -8
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +2 -4
- data/lib/datadog/core/process_discovery.rb +48 -23
- data/lib/datadog/core/rate_limiter.rb +9 -1
- data/lib/datadog/core/remote/client/capabilities.rb +7 -0
- data/lib/datadog/core/remote/client.rb +14 -6
- data/lib/datadog/core/remote/component.rb +10 -10
- data/lib/datadog/core/remote/configuration/content.rb +15 -2
- data/lib/datadog/core/remote/configuration/digest.rb +14 -7
- data/lib/datadog/core/remote/configuration/repository.rb +1 -1
- data/lib/datadog/core/remote/configuration/target.rb +13 -6
- data/lib/datadog/core/remote/transport/config.rb +4 -25
- data/lib/datadog/core/remote/transport/http/config.rb +10 -50
- data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
- data/lib/datadog/core/remote/transport/http.rb +15 -24
- data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
- data/lib/datadog/core/remote/worker.rb +25 -37
- data/lib/datadog/core/runtime/ext.rb +0 -1
- data/lib/datadog/core/runtime/metrics.rb +11 -1
- data/lib/datadog/core/semaphore.rb +1 -4
- data/lib/datadog/core/tag_builder.rb +0 -4
- data/lib/datadog/core/tag_normalizer.rb +84 -0
- data/lib/datadog/core/telemetry/component.rb +69 -15
- data/lib/datadog/core/telemetry/emitter.rb +6 -6
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +89 -51
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
- data/lib/datadog/core/telemetry/event.rb +1 -0
- data/lib/datadog/core/telemetry/logger.rb +2 -2
- data/lib/datadog/core/telemetry/logging.rb +2 -8
- data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
- data/lib/datadog/core/telemetry/request.rb +17 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +3 -34
- data/lib/datadog/core/telemetry/transport/http.rb +21 -16
- data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -11
- data/lib/datadog/core/telemetry/worker.rb +88 -32
- data/lib/datadog/core/transport/ext.rb +2 -0
- data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
- data/lib/datadog/core/transport/http/api/instance.rb +4 -21
- data/lib/datadog/core/transport/http/builder.rb +9 -5
- data/lib/datadog/core/transport/http/client.rb +80 -0
- data/lib/datadog/core/transport/http.rb +22 -19
- data/lib/datadog/core/transport/response.rb +15 -1
- data/lib/datadog/core/transport/transport.rb +90 -0
- data/lib/datadog/core/utils/array.rb +29 -0
- data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
- data/lib/datadog/core/utils/network.rb +22 -1
- data/lib/datadog/core/utils/only_once_successful.rb +8 -2
- data/lib/datadog/core/utils/safe_dup.rb +2 -2
- data/lib/datadog/core/utils/sequence.rb +2 -0
- data/lib/datadog/core/utils/time.rb +1 -1
- data/lib/datadog/core/utils.rb +2 -0
- data/lib/datadog/core/workers/async.rb +10 -1
- data/lib/datadog/core/workers/interval_loop.rb +44 -3
- data/lib/datadog/core/workers/polling.rb +2 -0
- data/lib/datadog/core/workers/queue.rb +100 -1
- data/lib/datadog/core.rb +2 -0
- data/lib/datadog/data_streams/configuration/settings.rb +49 -0
- data/lib/datadog/data_streams/configuration.rb +11 -0
- data/lib/datadog/data_streams/ext.rb +11 -0
- data/lib/datadog/data_streams/extensions.rb +16 -0
- data/lib/datadog/data_streams/pathway_context.rb +169 -0
- data/lib/datadog/data_streams/processor.rb +509 -0
- data/lib/datadog/data_streams/transport/http/stats.rb +52 -0
- data/lib/datadog/data_streams/transport/http.rb +40 -0
- data/lib/datadog/data_streams/transport/stats.rb +46 -0
- data/lib/datadog/data_streams.rb +100 -0
- data/lib/datadog/di/boot.rb +7 -3
- data/lib/datadog/di/component.rb +14 -16
- data/lib/datadog/di/context.rb +70 -0
- data/lib/datadog/di/contrib/active_record.rb +30 -5
- data/lib/datadog/di/el/compiler.rb +168 -0
- data/lib/datadog/di/el/evaluator.rb +159 -0
- data/lib/datadog/di/el/expression.rb +42 -0
- data/lib/datadog/di/el.rb +5 -0
- data/lib/datadog/di/error.rb +34 -0
- data/lib/datadog/di/instrumenter.rb +189 -55
- data/lib/datadog/di/logger.rb +2 -2
- data/lib/datadog/di/probe.rb +55 -15
- data/lib/datadog/di/probe_builder.rb +41 -2
- data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +1 -1
- data/lib/datadog/di/probe_manager.rb +50 -35
- data/lib/datadog/di/probe_notification_builder.rb +121 -70
- data/lib/datadog/di/probe_notifier_worker.rb +5 -5
- data/lib/datadog/di/proc_responder.rb +32 -0
- data/lib/datadog/di/remote.rb +89 -84
- data/lib/datadog/di/serializer.rb +151 -7
- data/lib/datadog/di/transport/diagnostics.rb +8 -36
- data/lib/datadog/di/transport/http/diagnostics.rb +1 -33
- data/lib/datadog/di/transport/http/input.rb +1 -33
- data/lib/datadog/di/transport/http.rb +32 -17
- data/lib/datadog/di/transport/input.rb +67 -34
- data/lib/datadog/di.rb +61 -5
- data/lib/datadog/error_tracking/filters.rb +2 -2
- data/lib/datadog/kit/appsec/events/v2.rb +2 -3
- data/lib/datadog/open_feature/component.rb +60 -0
- data/lib/datadog/open_feature/configuration.rb +27 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
- data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
- data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
- data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
- data/lib/datadog/open_feature/exposures/event.rb +60 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
- data/lib/datadog/open_feature/exposures/worker.rb +116 -0
- data/lib/datadog/open_feature/ext.rb +14 -0
- data/lib/datadog/open_feature/native_evaluator.rb +38 -0
- data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
- data/lib/datadog/open_feature/provider.rb +141 -0
- data/lib/datadog/open_feature/remote.rb +67 -0
- data/lib/datadog/open_feature/resolution_details.rb +35 -0
- data/lib/datadog/open_feature/transport.rb +70 -0
- data/lib/datadog/open_feature.rb +19 -0
- data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
- data/lib/datadog/opentelemetry/metrics.rb +117 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +26 -2
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +35 -0
- data/lib/datadog/opentelemetry.rb +3 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +41 -7
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +6 -5
- data/lib/datadog/profiling/component.rb +12 -11
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
- data/lib/datadog/profiling/ext.rb +2 -1
- data/lib/datadog/profiling/http_transport.rb +5 -2
- data/lib/datadog/profiling/profiler.rb +4 -0
- data/lib/datadog/profiling/tag_builder.rb +36 -3
- data/lib/datadog/profiling/tasks/exec.rb +2 -2
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/tracing/component.rb +6 -17
- data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
- data/lib/datadog/tracing/configuration/ext.rb +9 -3
- data/lib/datadog/tracing/configuration/settings.rb +89 -10
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/component.rb +2 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/extensions.rb +10 -2
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +84 -43
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
- data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +7 -1
- data/lib/datadog/tracing/contrib/rails/ext.rb +2 -1
- data/lib/datadog/tracing/contrib/rails/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +9 -1
- data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop.rb +41 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -2
- data/lib/datadog/tracing/metadata/ext.rb +9 -1
- data/lib/datadog/tracing/remote.rb +1 -9
- data/lib/datadog/tracing/sampling/priority_sampler.rb +3 -1
- data/lib/datadog/tracing/span.rb +1 -1
- data/lib/datadog/tracing/span_event.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +20 -9
- data/lib/datadog/tracing/trace_operation.rb +44 -6
- data/lib/datadog/tracing/tracer.rb +42 -16
- data/lib/datadog/tracing/transport/http/client.rb +12 -26
- data/lib/datadog/tracing/transport/http/traces.rb +2 -50
- data/lib/datadog/tracing/transport/http.rb +15 -9
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
- data/lib/datadog/tracing/transport/traces.rb +9 -71
- data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
- data/lib/datadog/tracing/writer.rb +1 -0
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +3 -0
- metadata +110 -24
- data/ext/libdatadog_api/macos_development.md +0 -26
- data/lib/datadog/core/remote/transport/http/api.rb +0 -53
- data/lib/datadog/core/remote/transport/http/client.rb +0 -49
- data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
- data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
- data/lib/datadog/core/transport/http/api/spec.rb +0 -36
- data/lib/datadog/di/transport/http/api.rb +0 -42
- data/lib/datadog/di/transport/http/client.rb +0 -47
- data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
- data/lib/datadog/tracing/transport/http/api.rb +0 -44
data/lib/datadog/di/error.rb
CHANGED
|
@@ -10,6 +10,10 @@ module Datadog
|
|
|
10
10
|
#
|
|
11
11
|
# @api private
|
|
12
12
|
class Error < StandardError
|
|
13
|
+
# Internal Dynamic Instrumentation error ("should never happen").
|
|
14
|
+
class InternalError < Error
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
# Probe does not contain a line number (i.e., is not a line probe).
|
|
14
18
|
class MissingLineNumber < Error
|
|
15
19
|
end
|
|
@@ -38,6 +42,11 @@ module Datadog
|
|
|
38
42
|
class ProbePreviouslyFailed < Error
|
|
39
43
|
end
|
|
40
44
|
|
|
45
|
+
# Raised when trying to instrument a probe when there is existing
|
|
46
|
+
# instrumentation for the same probe id.
|
|
47
|
+
class AlreadyInstrumented < Error
|
|
48
|
+
end
|
|
49
|
+
|
|
41
50
|
# Raised when installing a line probe and multiple files match the
|
|
42
51
|
# specified path suffix.
|
|
43
52
|
# A probe must be installed into one file only, since UI only
|
|
@@ -48,6 +57,31 @@ module Datadog
|
|
|
48
57
|
# and the user will need to make their suffix more precise.
|
|
49
58
|
class MultiplePathsMatch < Error
|
|
50
59
|
end
|
|
60
|
+
|
|
61
|
+
# Base class for exceptions arising during expression language AST
|
|
62
|
+
# compilation into Ruby code.
|
|
63
|
+
#
|
|
64
|
+
# Expression language does not specify behavior in all cases,
|
|
65
|
+
# leaving some choices to the language implementation in the tracers.
|
|
66
|
+
# It is therefore possible that some technically valid expressions are
|
|
67
|
+
# prohibited by our implementation.
|
|
68
|
+
#
|
|
69
|
+
# It is also possible that the sanitizers/validators prohibit some
|
|
70
|
+
# esoteric constructs that are technically valid in Ruby,
|
|
71
|
+
# for example if instance variable name rules are relaxed to allow
|
|
72
|
+
# arbitrary characters in them as permitted in method names.
|
|
73
|
+
class InvalidExpression < Error
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Variable name with invalid characters in an expression language
|
|
77
|
+
# expression.
|
|
78
|
+
class BadVariableName < InvalidExpression
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Base class for exceptions arising when evaluating expression language
|
|
82
|
+
# expressions.
|
|
83
|
+
class ExpressionEvaluationError < Error
|
|
84
|
+
end
|
|
51
85
|
end
|
|
52
86
|
end
|
|
53
87
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative '../core/utils/time'
|
|
4
4
|
|
|
5
5
|
# rubocop:disable Lint/AssignmentInCondition
|
|
6
|
+
# rubocop:disable Style/AndOr
|
|
6
7
|
|
|
7
8
|
module Datadog
|
|
8
9
|
module DI
|
|
@@ -88,11 +89,7 @@ module Datadog
|
|
|
88
89
|
# from the method but from outside of the method).
|
|
89
90
|
Location = Struct.new(:path, :lineno, :label)
|
|
90
91
|
|
|
91
|
-
def hook_method(probe,
|
|
92
|
-
unless block
|
|
93
|
-
raise ArgumentError, 'block is required'
|
|
94
|
-
end
|
|
95
|
-
|
|
92
|
+
def hook_method(probe, responder)
|
|
96
93
|
lock.synchronize do
|
|
97
94
|
if probe.instrumentation_module
|
|
98
95
|
# Already instrumented, warn?
|
|
@@ -117,8 +114,53 @@ module Datadog
|
|
|
117
114
|
settings = self.settings
|
|
118
115
|
|
|
119
116
|
mod = Module.new do
|
|
120
|
-
define_method(method_name) do |*args, **kwargs, &target_block| # steep:ignore
|
|
121
|
-
|
|
117
|
+
define_method(method_name) do |*args, **kwargs, &target_block| # steep:ignore NoMethod
|
|
118
|
+
# Steep: Unsure why it cannot detect kwargs in this block. Workaround:
|
|
119
|
+
# @type var kwargs: ::Hash[::Symbol, untyped]
|
|
120
|
+
continue = true
|
|
121
|
+
if condition = probe.condition
|
|
122
|
+
begin
|
|
123
|
+
# This context will be recreated later, unlike for line probes.
|
|
124
|
+
context = Context.new(
|
|
125
|
+
locals: serializer.combine_args(args, kwargs, self),
|
|
126
|
+
target_self: self,
|
|
127
|
+
probe: probe, settings: settings, serializer: serializer,
|
|
128
|
+
caller_locations: caller_locations,
|
|
129
|
+
)
|
|
130
|
+
continue = condition.satisfied?(context)
|
|
131
|
+
rescue => exc
|
|
132
|
+
# Evaluation error exception can be raised for "expected"
|
|
133
|
+
# errors, we probably need another setting to control whether
|
|
134
|
+
# these exceptions are propagated.
|
|
135
|
+
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions &&
|
|
136
|
+
!exc.is_a?(DI::Error::ExpressionEvaluationError)
|
|
137
|
+
|
|
138
|
+
if context
|
|
139
|
+
# We want to report evaluation errors for conditions
|
|
140
|
+
# as probe snapshots. However, if we failed to create
|
|
141
|
+
# the context, we won't be able to report anything as
|
|
142
|
+
# the probe notifier builder requires a context.
|
|
143
|
+
begin
|
|
144
|
+
responder.probe_condition_evaluation_failed_callback(context, exc)
|
|
145
|
+
rescue
|
|
146
|
+
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
147
|
+
|
|
148
|
+
# TODO log / report via telemetry?
|
|
149
|
+
end
|
|
150
|
+
else
|
|
151
|
+
_ = 42 # stop standard from wrecking this code
|
|
152
|
+
|
|
153
|
+
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
154
|
+
|
|
155
|
+
# TODO log / report via telemetry?
|
|
156
|
+
# If execution gets here, there is probably a bug in the tracer.
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
continue = false
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if continue and rate_limiter.nil? || rate_limiter.allow?
|
|
122
164
|
# Arguments may be mutated by the method, therefore
|
|
123
165
|
# they need to be serialized prior to method invocation.
|
|
124
166
|
serialized_entry_args = if probe.capture_snapshot?
|
|
@@ -126,21 +168,34 @@ module Datadog
|
|
|
126
168
|
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
|
127
169
|
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count)
|
|
128
170
|
end
|
|
129
|
-
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
171
|
+
# We intentionally do not use Core::Utils::Time.get_time
|
|
172
|
+
# here because the time provider may be overridden by the
|
|
173
|
+
# customer, and DI is not allowed to invoke customer code.
|
|
174
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
175
|
+
|
|
176
|
+
rv = nil
|
|
177
|
+
begin
|
|
178
|
+
# Under Ruby 2.6 we cannot just call super(*args, **kwargs)
|
|
179
|
+
# for methods defined via method_missing.
|
|
180
|
+
rv = if args.any?
|
|
181
|
+
if kwargs.any?
|
|
182
|
+
super(*args, **kwargs, &target_block)
|
|
183
|
+
else
|
|
184
|
+
super(*args, &target_block)
|
|
185
|
+
end
|
|
186
|
+
elsif kwargs.any?
|
|
187
|
+
super(**kwargs, &target_block)
|
|
135
188
|
else
|
|
136
|
-
super(
|
|
189
|
+
super(&target_block)
|
|
137
190
|
end
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
191
|
+
rescue NoMemoryError, Interrupt, SystemExit
|
|
192
|
+
raise
|
|
193
|
+
rescue Exception => exc # standard:disable Lint/RescueException
|
|
194
|
+
# We will raise the exception captured here later, after
|
|
195
|
+
# the instrumentation callback runs.
|
|
142
196
|
end
|
|
143
|
-
|
|
197
|
+
|
|
198
|
+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
|
|
144
199
|
# The method itself is not part of the stack trace because
|
|
145
200
|
# we are getting the stack trace from outside of the method.
|
|
146
201
|
# Add the method in manually as the top frame.
|
|
@@ -156,14 +211,22 @@ module Datadog
|
|
|
156
211
|
# that location here.
|
|
157
212
|
[]
|
|
158
213
|
end
|
|
159
|
-
|
|
214
|
+
# Steep: https://github.com/ruby/rbs/pull/2745
|
|
215
|
+
caller_locs = method_frame + caller_locations # steep:ignore ArgumentTypeMismatch
|
|
160
216
|
# TODO capture arguments at exit
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
217
|
+
|
|
218
|
+
context = Context.new(locals: nil, target_self: self,
|
|
219
|
+
probe: probe, settings: settings, serializer: serializer,
|
|
220
|
+
serialized_entry_args: serialized_entry_args,
|
|
221
|
+
caller_locations: caller_locs,
|
|
222
|
+
return_value: rv, duration: duration, exception: exc,)
|
|
223
|
+
|
|
224
|
+
responder.probe_executed_callback(context)
|
|
225
|
+
if exc
|
|
226
|
+
raise exc
|
|
227
|
+
else
|
|
228
|
+
rv
|
|
229
|
+
end
|
|
167
230
|
else
|
|
168
231
|
# stop standard from trying to mess up my code
|
|
169
232
|
_ = 42
|
|
@@ -199,6 +262,8 @@ module Datadog
|
|
|
199
262
|
|
|
200
263
|
probe.instrumentation_module = mod
|
|
201
264
|
cls.send(:prepend, mod)
|
|
265
|
+
|
|
266
|
+
DI.instrumented_count_inc(:method)
|
|
202
267
|
end
|
|
203
268
|
end
|
|
204
269
|
|
|
@@ -211,6 +276,8 @@ module Datadog
|
|
|
211
276
|
if mod = probe.instrumentation_module
|
|
212
277
|
mod.send(:remove_method, probe.method_name)
|
|
213
278
|
probe.instrumentation_module = nil
|
|
279
|
+
|
|
280
|
+
DI.instrumented_count_dec(:method)
|
|
214
281
|
end
|
|
215
282
|
end
|
|
216
283
|
end
|
|
@@ -220,11 +287,7 @@ module Datadog
|
|
|
220
287
|
# not for eval'd code, unless the eval'd code is associated with
|
|
221
288
|
# a file name and client invokes this method with the correct
|
|
222
289
|
# file name for the eval'd code.
|
|
223
|
-
def hook_line(probe,
|
|
224
|
-
unless block
|
|
225
|
-
raise ArgumentError, 'No block given to hook_line'
|
|
226
|
-
end
|
|
227
|
-
|
|
290
|
+
def hook_line(probe, responder)
|
|
228
291
|
lock.synchronize do
|
|
229
292
|
if probe.instrumentation_trace_point
|
|
230
293
|
# Already instrumented, warn?
|
|
@@ -245,7 +308,10 @@ module Datadog
|
|
|
245
308
|
|
|
246
309
|
iseq = nil
|
|
247
310
|
if code_tracker
|
|
248
|
-
|
|
311
|
+
# Steep: Complex type narrowing (before calling hook_line,
|
|
312
|
+
# we check that probe.line? is true which itself checks that probe.file is not nil)
|
|
313
|
+
# Annotation do not work here as `file` is a method on probe, not a local variable.
|
|
314
|
+
ret = code_tracker.iseqs_for_path_suffix(probe.file) # steep:ignore ArgumentTypeMismatch
|
|
249
315
|
unless ret
|
|
250
316
|
if permit_untargeted_trace_points
|
|
251
317
|
# Continue withoout targeting the trace point.
|
|
@@ -307,27 +373,86 @@ module Datadog
|
|
|
307
373
|
# are invoked for *each* line of Ruby executed.
|
|
308
374
|
# TODO find out exactly when the path in trace point is relative.
|
|
309
375
|
# Looks like this is the case when line trace point is not targeted?
|
|
310
|
-
|
|
376
|
+
continue = iseq || tp.lineno == probe.line_no && (
|
|
311
377
|
probe.file == tp.path || probe.file_matches?(tp.path)
|
|
312
378
|
)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
379
|
+
|
|
380
|
+
# We set the trace point on :return to be able to instrument
|
|
381
|
+
# 'end' lines. This also causes the trace point to be invoked on
|
|
382
|
+
# non-'end' lines when a line raises an exception, since the
|
|
383
|
+
# exception causes the method to stop executing and stack unwends.
|
|
384
|
+
# We do not want two invocations of the trace point.
|
|
385
|
+
# Therefore, if a trace point is invoked with a :line event,
|
|
386
|
+
# mark it as such and ignore subsequent :return events.
|
|
387
|
+
continue &&= if probe.executed_on_line?
|
|
388
|
+
tp.event == :line
|
|
389
|
+
else
|
|
390
|
+
if tp.event == :line
|
|
391
|
+
probe.executed_on_line!
|
|
392
|
+
end
|
|
393
|
+
true
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
if continue
|
|
397
|
+
if condition = probe.condition
|
|
398
|
+
begin
|
|
399
|
+
context = Context.new(
|
|
400
|
+
locals: Instrumenter.get_local_variables(tp),
|
|
401
|
+
target_self: tp.self,
|
|
402
|
+
probe: probe, settings: settings, serializer: serializer,
|
|
403
|
+
path: tp.path,
|
|
404
|
+
caller_locations: caller_locations,
|
|
405
|
+
)
|
|
406
|
+
continue = condition.satisfied?(context)
|
|
407
|
+
rescue => exc
|
|
408
|
+
# Evaluation error exception can be raised for "expected"
|
|
409
|
+
# errors, we probably need another setting to control whether
|
|
410
|
+
# these exceptions are propagated.
|
|
411
|
+
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions &&
|
|
412
|
+
!exc.is_a?(DI::Error::ExpressionEvaluationError)
|
|
413
|
+
|
|
414
|
+
continue = false
|
|
415
|
+
if context
|
|
416
|
+
# We want to report evaluation errors for conditions
|
|
417
|
+
# as probe snapshots. However, if we failed to create
|
|
418
|
+
# the context, we won't be able to report anything as
|
|
419
|
+
# the probe notifier builder requires a context.
|
|
420
|
+
begin
|
|
421
|
+
responder.probe_condition_evaluation_failed_callback(context, condition, exc)
|
|
422
|
+
rescue
|
|
423
|
+
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
424
|
+
|
|
425
|
+
# TODO log / report via telemetry?
|
|
426
|
+
end
|
|
427
|
+
else
|
|
428
|
+
_ = 42 # stop standard from wrecking this code
|
|
429
|
+
|
|
430
|
+
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
431
|
+
|
|
432
|
+
# TODO log / report via telemetry?
|
|
433
|
+
# If execution gets here, there is probably a bug in the tracer.
|
|
434
|
+
end
|
|
323
435
|
end
|
|
324
|
-
# & is to stop steep complaints, block is always present here.
|
|
325
|
-
block&.call(probe: probe,
|
|
326
|
-
serialized_locals: serialized_locals,
|
|
327
|
-
target_self: tp.self,
|
|
328
|
-
path: tp.path, caller_locations: caller_locations)
|
|
329
436
|
end
|
|
330
437
|
end
|
|
438
|
+
|
|
439
|
+
continue &&= rate_limiter.nil? || rate_limiter.allow? # standard:disable Style/AndOr
|
|
440
|
+
|
|
441
|
+
if continue
|
|
442
|
+
# The context creation is relatively expensive and we don't
|
|
443
|
+
# want to run it if the callback won't be executed due to the
|
|
444
|
+
# rate limit.
|
|
445
|
+
# Thus the copy-paste of the creation call here.
|
|
446
|
+
context ||= Context.new(
|
|
447
|
+
locals: Instrumenter.get_local_variables(tp),
|
|
448
|
+
target_self: tp.self,
|
|
449
|
+
probe: probe, settings: settings, serializer: serializer,
|
|
450
|
+
path: tp.path,
|
|
451
|
+
caller_locations: caller_locations,
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
responder.probe_executed_callback(context)
|
|
455
|
+
end
|
|
331
456
|
rescue => exc
|
|
332
457
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
333
458
|
logger.debug { "di: unhandled exception in line trace point: #{exc.class}: #{exc}" }
|
|
@@ -341,9 +466,11 @@ module Datadog
|
|
|
341
466
|
# TODO test this path
|
|
342
467
|
end
|
|
343
468
|
|
|
344
|
-
#
|
|
469
|
+
# Internal sanity check - untargeted trace points create a huge
|
|
470
|
+
# performance impact, and we absolutely do not want to set them
|
|
471
|
+
# accidentally.
|
|
345
472
|
if !iseq && !permit_untargeted_trace_points
|
|
346
|
-
raise "Trying to use an untargeted trace point when user did not permit it"
|
|
473
|
+
raise Error::InternalError, "Trying to use an untargeted trace point when user did not permit it"
|
|
347
474
|
end
|
|
348
475
|
|
|
349
476
|
lock.synchronize do
|
|
@@ -356,12 +483,16 @@ module Datadog
|
|
|
356
483
|
# actual_path could be nil if we don't use targeted trace points.
|
|
357
484
|
probe.instrumented_path = actual_path
|
|
358
485
|
|
|
359
|
-
|
|
486
|
+
# TracePoint#enable returns false when it succeeds.
|
|
487
|
+
rv = if iseq
|
|
360
488
|
tp.enable(target: iseq, target_line: line_no)
|
|
361
489
|
else
|
|
362
490
|
tp.enable
|
|
363
491
|
end
|
|
364
|
-
|
|
492
|
+
|
|
493
|
+
DI.instrumented_count_inc(:line)
|
|
494
|
+
|
|
495
|
+
rv
|
|
365
496
|
end
|
|
366
497
|
true
|
|
367
498
|
end
|
|
@@ -371,15 +502,17 @@ module Datadog
|
|
|
371
502
|
if tp = probe.instrumentation_trace_point
|
|
372
503
|
tp.disable
|
|
373
504
|
probe.instrumentation_trace_point = nil
|
|
505
|
+
|
|
506
|
+
DI.instrumented_count_dec(:line)
|
|
374
507
|
end
|
|
375
508
|
end
|
|
376
509
|
end
|
|
377
510
|
|
|
378
|
-
def hook(probe,
|
|
511
|
+
def hook(probe, responder)
|
|
379
512
|
if probe.method?
|
|
380
|
-
hook_method(probe,
|
|
513
|
+
hook_method(probe, responder)
|
|
381
514
|
elsif probe.line?
|
|
382
|
-
hook_line(probe,
|
|
515
|
+
hook_line(probe, responder)
|
|
383
516
|
else
|
|
384
517
|
# TODO add test coverage for this path
|
|
385
518
|
logger.debug { "di: unknown probe type to hook: #{probe}" }
|
|
@@ -449,3 +582,4 @@ module Datadog
|
|
|
449
582
|
end
|
|
450
583
|
|
|
451
584
|
# rubocop:enable Lint/AssignmentInCondition
|
|
585
|
+
# rubocop:enable Style/AndOr
|
data/lib/datadog/di/logger.rb
CHANGED
|
@@ -8,7 +8,7 @@ module Datadog
|
|
|
8
8
|
#
|
|
9
9
|
# @api private
|
|
10
10
|
class Logger
|
|
11
|
-
extend Forwardable
|
|
11
|
+
extend Forwardable
|
|
12
12
|
|
|
13
13
|
def initialize(settings, target)
|
|
14
14
|
@settings = settings
|
|
@@ -18,7 +18,7 @@ module Datadog
|
|
|
18
18
|
attr_reader :settings
|
|
19
19
|
attr_reader :target
|
|
20
20
|
|
|
21
|
-
def_delegators :target, :debug
|
|
21
|
+
def_delegators :target, :debug
|
|
22
22
|
|
|
23
23
|
def trace(&block)
|
|
24
24
|
if settings.dynamic_instrumentation.internal.trace_logging
|
data/lib/datadog/di/probe.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Datadog
|
|
|
17
17
|
# and remote config code must be prepared to deal with exceptions
|
|
18
18
|
# raised by Probe constructor in particular. Therefore, Probe constructor
|
|
19
19
|
# will raise an exception if it determines that there is not enough
|
|
20
|
-
# information (or
|
|
20
|
+
# information (or conflicting information) in the arguments to create a
|
|
21
21
|
# functional probe, and upstream code is tasked with not spamming logs
|
|
22
22
|
# with notifications of such errors (and potentially limiting the
|
|
23
23
|
# attempts to construct probe from a given payload).
|
|
@@ -36,8 +36,9 @@ module Datadog
|
|
|
36
36
|
|
|
37
37
|
def initialize(id:, type:,
|
|
38
38
|
file: nil, line_no: nil, type_name: nil, method_name: nil,
|
|
39
|
-
template: nil,
|
|
40
|
-
|
|
39
|
+
template: nil, template_segments: nil,
|
|
40
|
+
capture_snapshot: false, max_capture_depth: nil,
|
|
41
|
+
max_capture_attribute_count: nil, condition: nil,
|
|
41
42
|
rate_limit: nil)
|
|
42
43
|
# Perform some sanity checks here to detect unexpected attribute
|
|
43
44
|
# combinations, in order to not do them in subsequent code.
|
|
@@ -45,9 +46,17 @@ module Datadog
|
|
|
45
46
|
raise ArgumentError, "Unknown probe type: #{type}"
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
if
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
# Probe should be inferred to be a line probe if the specification
|
|
50
|
+
# contains a line number. This how Java tracer works and Go tracer
|
|
51
|
+
# is implementing the same behavior, and Go will have all 3 fields
|
|
52
|
+
# (file path, line number and method name) for line probes.
|
|
53
|
+
# Do not raise if line number and method name both exist - instead
|
|
54
|
+
# treat the probe as a line probe.
|
|
55
|
+
#
|
|
56
|
+
# In the future we want to provide type name and method name to line
|
|
57
|
+
# probes, so that the library can verify that the instrumented line
|
|
58
|
+
# is in the method that the frontend showed to the user when the
|
|
59
|
+
# user created the probe.
|
|
51
60
|
|
|
52
61
|
if line_no && !file
|
|
53
62
|
raise ArgumentError, "Probe contains line number but not file: #{id}"
|
|
@@ -57,6 +66,10 @@ module Datadog
|
|
|
57
66
|
raise ArgumentError, "Partial method probe definition: #{id}"
|
|
58
67
|
end
|
|
59
68
|
|
|
69
|
+
if line_no.nil? && method_name.nil?
|
|
70
|
+
raise ArgumentError, "Unhandled probe type: neither method nor line probe: #{id}"
|
|
71
|
+
end
|
|
72
|
+
|
|
60
73
|
@id = id
|
|
61
74
|
@type = type
|
|
62
75
|
@file = file
|
|
@@ -64,21 +77,25 @@ module Datadog
|
|
|
64
77
|
@type_name = type_name
|
|
65
78
|
@method_name = method_name
|
|
66
79
|
@template = template
|
|
80
|
+
@template_segments = template_segments
|
|
67
81
|
@capture_snapshot = !!capture_snapshot
|
|
68
82
|
@max_capture_depth = max_capture_depth
|
|
69
83
|
@max_capture_attribute_count = max_capture_attribute_count
|
|
70
|
-
|
|
71
|
-
# These checks use instance methods that have more complex logic
|
|
72
|
-
# than checking a single argument value. To avoid duplicating
|
|
73
|
-
# the logic here, use the methods and perform these checks after
|
|
74
|
-
# instance variable assignment.
|
|
75
|
-
unless method? || line?
|
|
76
|
-
raise ArgumentError, "Unhandled probe type: neither method nor line probe: #{id}"
|
|
77
|
-
end
|
|
84
|
+
@condition = condition
|
|
78
85
|
|
|
79
86
|
@rate_limit = rate_limit || (@capture_snapshot ? 1 : 5000)
|
|
80
87
|
@rate_limiter = Datadog::Core::TokenBucket.new(@rate_limit)
|
|
81
88
|
|
|
89
|
+
# At most one report per second.
|
|
90
|
+
# We create the rate limiter here even though it may never be used,
|
|
91
|
+
# to avoid having to synchronize the creation since method probes
|
|
92
|
+
# can be executed on multiple threads concurrently (even if line
|
|
93
|
+
# probes are never executed concurrently since those are done in a
|
|
94
|
+
# trace point).
|
|
95
|
+
if condition
|
|
96
|
+
@condition_evaluation_failed_rate_limiter = Datadog::Core::TokenBucket.new(1)
|
|
97
|
+
end
|
|
98
|
+
|
|
82
99
|
@emitting_notified = false
|
|
83
100
|
end
|
|
84
101
|
|
|
@@ -89,6 +106,10 @@ module Datadog
|
|
|
89
106
|
attr_reader :type_name
|
|
90
107
|
attr_reader :method_name
|
|
91
108
|
attr_reader :template
|
|
109
|
+
attr_reader :template_segments
|
|
110
|
+
|
|
111
|
+
# The compiled condition for the probe, as a String.
|
|
112
|
+
attr_reader :condition
|
|
92
113
|
|
|
93
114
|
# Configured maximum capture depth. Can be nil in which case
|
|
94
115
|
# the global default will be used.
|
|
@@ -104,6 +125,16 @@ module Datadog
|
|
|
104
125
|
# Rate limiter object. For internal DI use only.
|
|
105
126
|
attr_reader :rate_limiter
|
|
106
127
|
|
|
128
|
+
# Rate limiter object for sending snapshots with evaluation errors
|
|
129
|
+
# for when probe condition evaluation fails.
|
|
130
|
+
# This rate limit is separate from the "base" rate limit for the probe
|
|
131
|
+
# because when the condition evaluation succeeds we want the "base"
|
|
132
|
+
# rate limit applied, not tainted by any evaluation errors
|
|
133
|
+
# (for example, the condition can be highly selective, and when it
|
|
134
|
+
# does not hold the evaluation may fail - we don't want to use up the
|
|
135
|
+
# probe rate limit for the errors).
|
|
136
|
+
attr_reader :condition_evaluation_failed_rate_limiter
|
|
137
|
+
|
|
107
138
|
def capture_snapshot?
|
|
108
139
|
@capture_snapshot
|
|
109
140
|
end
|
|
@@ -122,7 +153,7 @@ module Datadog
|
|
|
122
153
|
|
|
123
154
|
# Returns whether the probe is a method probe.
|
|
124
155
|
def method?
|
|
125
|
-
|
|
156
|
+
line_no.nil?
|
|
126
157
|
end
|
|
127
158
|
|
|
128
159
|
# Returns the line number associated with the probe, raising
|
|
@@ -186,6 +217,15 @@ module Datadog
|
|
|
186
217
|
def emitting_notified?
|
|
187
218
|
!!@emitting_notified
|
|
188
219
|
end
|
|
220
|
+
|
|
221
|
+
def executed_on_line?
|
|
222
|
+
!!@executed_on_line
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def executed_on_line!
|
|
226
|
+
# TODO lock?
|
|
227
|
+
@executed_on_line = true
|
|
228
|
+
end
|
|
189
229
|
end
|
|
190
230
|
end
|
|
191
231
|
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# rubocop:disable Lint/AssignmentInCondition
|
|
4
|
+
|
|
3
5
|
require_relative "probe"
|
|
6
|
+
require_relative 'el'
|
|
4
7
|
|
|
5
8
|
module Datadog
|
|
6
9
|
module DI
|
|
@@ -17,14 +20,24 @@ module Datadog
|
|
|
17
20
|
#
|
|
18
21
|
# @api private
|
|
19
22
|
module ProbeBuilder
|
|
20
|
-
|
|
23
|
+
# Steep: https://github.com/soutaro/steep/issues/363
|
|
24
|
+
PROBE_TYPES = { # steep:ignore IncompatibleAssignment
|
|
21
25
|
'LOG_PROBE' => :log,
|
|
22
26
|
}.freeze
|
|
23
27
|
|
|
24
|
-
module_function
|
|
28
|
+
module_function
|
|
29
|
+
|
|
30
|
+
def build_from_remote_config(config)
|
|
25
31
|
# The validations here are not yet comprehensive.
|
|
26
32
|
type = config.fetch('type')
|
|
27
33
|
type_symbol = PROBE_TYPES[type] or raise ArgumentError, "Unrecognized probe type: #{type}"
|
|
34
|
+
cond = if cond_spec = config['when']
|
|
35
|
+
unless cond_spec['dsl'] && cond_spec['json']
|
|
36
|
+
raise ArgumentError, "Malformed condition specification for probe: #{config}"
|
|
37
|
+
end
|
|
38
|
+
compiled = EL::Compiler.new.compile(cond_spec['json'])
|
|
39
|
+
EL::Expression.new(cond_spec['dsl'], compiled)
|
|
40
|
+
end
|
|
28
41
|
Probe.new(
|
|
29
42
|
id: config.fetch("id"),
|
|
30
43
|
type: type_symbol,
|
|
@@ -34,15 +47,41 @@ module Datadog
|
|
|
34
47
|
line_no: config["where"]&.[]("lines")&.compact&.map(&:to_i)&.first,
|
|
35
48
|
type_name: config["where"]&.[]("typeName"),
|
|
36
49
|
method_name: config["where"]&.[]("methodName"),
|
|
50
|
+
# We should not be using the template for anything - we instead
|
|
51
|
+
# use +segments+ - but keep the template for debugging.
|
|
37
52
|
template: config["template"],
|
|
53
|
+
template_segments: build_template_segments(config['segments']),
|
|
38
54
|
capture_snapshot: !!config["captureSnapshot"],
|
|
39
55
|
max_capture_depth: config["capture"]&.[]("maxReferenceDepth"),
|
|
40
56
|
max_capture_attribute_count: config["capture"]&.[]("maxFieldCount"),
|
|
41
57
|
rate_limit: config["sampling"]&.[]("snapshotsPerSecond"),
|
|
58
|
+
condition: cond,
|
|
42
59
|
)
|
|
43
60
|
rescue KeyError => exc
|
|
44
61
|
raise ArgumentError, "Malformed remote configuration entry for probe: #{exc.class}: #{exc}: #{config}"
|
|
45
62
|
end
|
|
63
|
+
|
|
64
|
+
def build_template_segments(segments)
|
|
65
|
+
segments&.map do |segment|
|
|
66
|
+
if Hash === segment
|
|
67
|
+
if str = segment['str']
|
|
68
|
+
str
|
|
69
|
+
elsif ast = segment['json']
|
|
70
|
+
unless dsl = segment['dsl']
|
|
71
|
+
raise ArgumentError, "Missing dsl for json in segment: #{segment}"
|
|
72
|
+
end
|
|
73
|
+
compiled = EL::Compiler.new.compile(ast)
|
|
74
|
+
EL::Expression.new(dsl, compiled)
|
|
75
|
+
else
|
|
76
|
+
# TODO report to telemetry?
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
# TODO report to telemetry?
|
|
80
|
+
end
|
|
81
|
+
end&.compact
|
|
82
|
+
end
|
|
46
83
|
end
|
|
47
84
|
end
|
|
48
85
|
end
|
|
86
|
+
|
|
87
|
+
# rubocop:enable Lint/AssignmentInCondition
|
|
@@ -6,7 +6,7 @@ module Datadog
|
|
|
6
6
|
# Railtie class initializes dynamic instrumentation contrib code
|
|
7
7
|
# in Rails environments.
|
|
8
8
|
class Railtie < Rails::Railtie
|
|
9
|
-
initializer 'datadog.dynamic_instrumentation.load_probe_file' do |app|
|
|
9
|
+
initializer 'datadog.dynamic_instrumentation.load_probe_file' do |app|
|
|
10
10
|
ProbeFileLoader.load_now
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -20,7 +20,7 @@ module Datadog
|
|
|
20
20
|
module_function def load_now
|
|
21
21
|
should_propagate = false
|
|
22
22
|
|
|
23
|
-
probe_file_path =
|
|
23
|
+
probe_file_path = DATADOG_ENV['DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE']
|
|
24
24
|
if probe_file_path.nil? || probe_file_path.empty?
|
|
25
25
|
return
|
|
26
26
|
end
|