datadog 2.39.0 → 2.41.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 +97 -44
- data/ext/datadog_profiling_native_extension/collectors_stack.c +219 -148
- data/ext/datadog_profiling_native_extension/collectors_stack.h +16 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +12 -7
- 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 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +12 -7
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +284 -76
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +16 -10
- data/ext/libdatadog_api/datadog_ruby_common.c +19 -11
- data/ext/libdatadog_api/datadog_ruby_common.h +7 -0
- data/ext/libdatadog_api/init.c +4 -0
- data/ext/libdatadog_api/trace_exporter.c +1312 -0
- data/ext/libdatadog_api/trace_exporter.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/api_client.rb +1 -1
- data/lib/datadog/ai_guard/evaluation/request.rb +8 -8
- data/lib/datadog/ai_guard/evaluation.rb +11 -3
- data/lib/datadog/ai_guard/ext.rb +3 -1
- 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/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 +2 -2
- 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 +2 -2
- 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 +3 -3
- data/lib/datadog/core/configuration/components.rb +2 -2
- 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 +33 -41
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
- 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 +1 -1
- data/lib/datadog/core/remote/client.rb +1 -1
- data/lib/datadog/core/remote/configuration/repository.rb +2 -2
- 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/data_streams/processor.rb +14 -14
- 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/instrumenter.rb +5 -4
- data/lib/datadog/di/probe_builder.rb +7 -6
- data/lib/datadog/di/probe_notification_builder.rb +2 -2
- data/lib/datadog/di/serializer.rb +29 -4
- data/lib/datadog/error_tracking/component.rb +1 -1
- data/lib/datadog/kit/appsec/events/v2.rb +2 -2
- data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
- data/lib/datadog/open_feature/exposures/event.rb +5 -5
- data/lib/datadog/profiling/collectors/info.rb +1 -1
- data/lib/datadog/profiling/collectors/thread_context.rb +6 -13
- data/lib/datadog/profiling/component.rb +1 -0
- data/lib/datadog/profiling/tasks/exec.rb +1 -1
- data/lib/datadog/profiling.rb +4 -0
- data/lib/datadog/symbol_database/extractor.rb +6 -6
- data/lib/datadog/tracing/component.rb +21 -0
- 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 +1 -0
- data/lib/datadog/tracing/configuration/settings.rb +16 -0
- 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.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/ext.rb +3 -3
- 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/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/sequel/database.rb +1 -5
- data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -1
- 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/waterdrop/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/correlation.rb +2 -2
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +2 -2
- data/lib/datadog/tracing/distributed/baggage.rb +1 -2
- data/lib/datadog/tracing/distributed/propagation_policy.rb +5 -0
- data/lib/datadog/tracing/metadata/tagging.rb +1 -1
- data/lib/datadog/tracing/remote.rb +2 -2
- 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/tracer.rb +8 -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.rb +387 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +1 -1
- data/lib/datadog/tracing/writer.rb +17 -4
- data/lib/datadog/version.rb +1 -1
- metadata +12 -7
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../../ruby_version"
|
|
4
|
+
|
|
5
|
+
require "timeout" if Datadog::RubyVersion.is?("< 3.2")
|
|
6
|
+
|
|
3
7
|
module Datadog
|
|
4
8
|
module DI
|
|
5
9
|
module EL
|
|
@@ -7,6 +11,20 @@ module Datadog
|
|
|
7
11
|
#
|
|
8
12
|
# @api private
|
|
9
13
|
class Evaluator
|
|
14
|
+
# Maximum wall-clock time allowed for evaluating a single `matches`
|
|
15
|
+
# operator.
|
|
16
|
+
MATCHES_TIMEOUT_SECONDS = 0.5
|
|
17
|
+
|
|
18
|
+
# @param regexps [Array<Regexp>] Regexps precompiled from literal
|
|
19
|
+
# `matches` patterns, looked up by index by #matches_compiled.
|
|
20
|
+
# Empty when the expression has no `matches` pattern with
|
|
21
|
+
# a direct regular expression argument.
|
|
22
|
+
def initialize(regexps = [])
|
|
23
|
+
@regexps = regexps
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_reader :regexps
|
|
27
|
+
|
|
10
28
|
def ref(var)
|
|
11
29
|
@context.fetch(var)
|
|
12
30
|
end
|
|
@@ -48,10 +66,72 @@ module Datadog
|
|
|
48
66
|
end
|
|
49
67
|
end
|
|
50
68
|
|
|
69
|
+
# Build a Regexp from a pattern string. On Ruby 3.2+ the per-match
|
|
70
|
+
# timeout (MATCHES_TIMEOUT_SECONDS) is baked into the compiled
|
|
71
|
+
# Regexp via the in-engine `timeout:` keyword, which interrupts the
|
|
72
|
+
# matcher at every backtrack step and reliably bounds matcher
|
|
73
|
+
# runtime regardless of pattern shape. On older Rubies the Regexp
|
|
74
|
+
# carries no timeout; the bound is applied at match time by
|
|
75
|
+
# #bounded_match? instead.
|
|
76
|
+
#
|
|
77
|
+
# @param needle [String] regexp source.
|
|
78
|
+
# @return [Regexp] compiled regexp, with baked-in timeout on Ruby 3.2+.
|
|
79
|
+
if Datadog::RubyVersion.is?(">= 3.2")
|
|
80
|
+
def self.compile_regexp(needle)
|
|
81
|
+
Regexp.new(needle, timeout: MATCHES_TIMEOUT_SECONDS)
|
|
82
|
+
end
|
|
83
|
+
else
|
|
84
|
+
def self.compile_regexp(needle)
|
|
85
|
+
Regexp.compile(needle)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Match +haystack+ against a regexp whose needle is computed at
|
|
90
|
+
# evaluation time, so the Regexp cannot be precompiled. Literal needles are
|
|
91
|
+
# precompiled by the Compiler and dispatched to #matches_compiled.
|
|
92
|
+
#
|
|
93
|
+
# @param haystack [String] string to match against.
|
|
94
|
+
# @param needle [String] regexp source.
|
|
95
|
+
# @return [Boolean] whether the haystack matches the regexp.
|
|
96
|
+
# @raise [Regexp::TimeoutError] (Ruby 3.2+) regexp engine exceeded MATCHES_TIMEOUT_SECONDS.
|
|
97
|
+
# @raise [Timeout::Error] (Ruby < 3.2) Timeout.timeout fired.
|
|
51
98
|
def matches(haystack, needle)
|
|
52
|
-
|
|
53
|
-
|
|
99
|
+
bounded_match?(Evaluator.compile_regexp(needle), haystack)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Match +haystack+ against a Regexp precompiled at expression-compile
|
|
103
|
+
# time, looked up by index in +regexps+.
|
|
104
|
+
#
|
|
105
|
+
# @param haystack [String] string to match against.
|
|
106
|
+
# @param index [Integer] position of the precompiled Regexp in +regexps+.
|
|
107
|
+
# @return [Boolean] whether the haystack matches the regexp.
|
|
108
|
+
# @raise [Regexp::TimeoutError] (Ruby 3.2+) regexp engine exceeded MATCHES_TIMEOUT_SECONDS.
|
|
109
|
+
# @raise [Timeout::Error] (Ruby < 3.2) Timeout.timeout fired.
|
|
110
|
+
def matches_compiled(haystack, index)
|
|
111
|
+
bounded_match?(regexps.fetch(index), haystack)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Match +haystack+ against +re+, bounded at MATCHES_TIMEOUT_SECONDS
|
|
115
|
+
# wall-clock.
|
|
116
|
+
#
|
|
117
|
+
# @param re [Regexp] regexp to match against.
|
|
118
|
+
# @param haystack [String] string to match against.
|
|
119
|
+
# @return [Boolean] whether the haystack matches the regexp.
|
|
120
|
+
if Datadog::RubyVersion.is?(">= 3.2")
|
|
121
|
+
def bounded_match?(re, haystack)
|
|
122
|
+
# Uses Regexp#match? rather than =~ so that the
|
|
123
|
+
# thread-local match data ($~, $1, ...) is not mutated as a side
|
|
124
|
+
# effect of DI expression evaluation.
|
|
125
|
+
re.match?(haystack)
|
|
126
|
+
end
|
|
127
|
+
else
|
|
128
|
+
def bounded_match?(re, haystack)
|
|
129
|
+
Timeout.timeout(MATCHES_TIMEOUT_SECONDS) do
|
|
130
|
+
re.match?(haystack)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
54
133
|
end
|
|
134
|
+
private :bounded_match?
|
|
55
135
|
|
|
56
136
|
def getmember(object, field)
|
|
57
137
|
object.instance_variable_get("@#{field}")
|
|
@@ -7,12 +7,22 @@ module Datadog
|
|
|
7
7
|
#
|
|
8
8
|
# @api private
|
|
9
9
|
class Expression
|
|
10
|
-
|
|
10
|
+
# @param dsl_expr [String] human-readable DSL form, kept for debugging.
|
|
11
|
+
# @param compiled_expr [String] Ruby source produced by Compiler#compile.
|
|
12
|
+
# @param regexps [Array<Regexp>] precompiled `matches` regexps (see
|
|
13
|
+
# Compiler#precompile_regexp), the second element returned by
|
|
14
|
+
# Compiler#compile.
|
|
15
|
+
# @param redaction_identifier [String, nil] the identifier this
|
|
16
|
+
# expression directly references at its top level (see
|
|
17
|
+
# Compiler#redaction_identifier); nil when it is not a direct
|
|
18
|
+
# reference.
|
|
19
|
+
def initialize(dsl_expr, compiled_expr, regexps: [], redaction_identifier: nil)
|
|
11
20
|
unless String === compiled_expr
|
|
12
21
|
raise ArgumentError, "compiled_expr must be a string"
|
|
13
22
|
end
|
|
14
23
|
|
|
15
24
|
@dsl_expr = dsl_expr
|
|
25
|
+
@redaction_identifier = redaction_identifier
|
|
16
26
|
|
|
17
27
|
cls = Class.new(Evaluator)
|
|
18
28
|
cls.class_exec do
|
|
@@ -23,11 +33,12 @@ module Datadog
|
|
|
23
33
|
end
|
|
24
34
|
RUBY
|
|
25
35
|
end
|
|
26
|
-
@evaluator = cls.new
|
|
36
|
+
@evaluator = cls.new(regexps)
|
|
27
37
|
end
|
|
28
38
|
|
|
29
39
|
attr_reader :dsl_expr
|
|
30
40
|
attr_reader :evaluator
|
|
41
|
+
attr_reader :redaction_identifier
|
|
31
42
|
|
|
32
43
|
def evaluate(context)
|
|
33
44
|
@evaluator.evaluate(context)
|
|
@@ -160,6 +160,7 @@ module Datadog
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
loc = target_method&.source_location
|
|
163
|
+
# @type var instrumenter: Instrumenter
|
|
163
164
|
instrumenter = self
|
|
164
165
|
|
|
165
166
|
mod = Module.new do
|
|
@@ -193,7 +194,7 @@ module Datadog
|
|
|
193
194
|
# user probe on Proc#call cannot intercept the trampoline, and no
|
|
194
195
|
# Proc is allocated for the block.
|
|
195
196
|
if RubyVersion.is?(">= 3")
|
|
196
|
-
define_method(method_name) do |*args, **kwargs, &target_block|
|
|
197
|
+
define_method(method_name) do |*args, **kwargs, &target_block|
|
|
197
198
|
# steep:ignore FallbackAny below: Steep cannot narrow the
|
|
198
199
|
# **kwargs parameter inside this define_method block, so it
|
|
199
200
|
# falls back to untyped at the super and run_method_probe sites.
|
|
@@ -211,7 +212,7 @@ module Datadog
|
|
|
211
212
|
end
|
|
212
213
|
end
|
|
213
214
|
else
|
|
214
|
-
define_method(method_name) do |*args, &target_block|
|
|
215
|
+
define_method(method_name) do |*args, &target_block|
|
|
215
216
|
if DI.in_probe?
|
|
216
217
|
return super(*args, &target_block)
|
|
217
218
|
end
|
|
@@ -230,7 +231,7 @@ module Datadog
|
|
|
230
231
|
super(*args, &target_block)
|
|
231
232
|
end
|
|
232
233
|
end
|
|
233
|
-
ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
|
|
234
|
+
ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
|
|
234
235
|
end
|
|
235
236
|
end
|
|
236
237
|
|
|
@@ -461,7 +462,7 @@ module Datadog
|
|
|
461
462
|
# @param args [Array] positional arguments passed to the probed method
|
|
462
463
|
# @param kwargs [Hash{Symbol => Object}] keyword arguments passed to the probed method
|
|
463
464
|
# @param target_block [Proc, nil] block argument passed to the probed method
|
|
464
|
-
# @param target_self [
|
|
465
|
+
# @param target_self [any] the receiver of the probed method invocation
|
|
465
466
|
# @param probe [Datadog::DI::Probe] the probe whose callback this invocation runs
|
|
466
467
|
# @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback] callback target invoked with the built Context
|
|
467
468
|
# @param loc [Array(String, Integer), nil] source location of the probed method, or nil for virtual/lazily-defined methods
|
|
@@ -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
|
|
@@ -179,7 +179,7 @@ module Datadog
|
|
|
179
179
|
if status == "ERROR"
|
|
180
180
|
diagnostics[:exception] = { # steep:ignore
|
|
181
181
|
type: exception ? exception.class.name : "Error",
|
|
182
|
-
message: exception ? exception.message : message
|
|
182
|
+
message: exception ? exception.message : message,
|
|
183
183
|
}
|
|
184
184
|
end
|
|
185
185
|
|
|
@@ -405,7 +405,7 @@ module Datadog
|
|
|
405
405
|
when String
|
|
406
406
|
segment
|
|
407
407
|
when EL::Expression
|
|
408
|
-
serializer.serialize_value_for_message(segment.evaluate(context))
|
|
408
|
+
serializer.serialize_value_for_message(segment.evaluate(context), name: segment.redaction_identifier)
|
|
409
409
|
else
|
|
410
410
|
raise ArgumentError, "Invalid template segment type: #{segment}"
|
|
411
411
|
end
|
|
@@ -50,6 +50,13 @@ module Datadog
|
|
|
50
50
|
# return a safe stub rather than tear the process down.
|
|
51
51
|
SERIALIZABLE_FATAL_EXCEPTION_CLASSES = [SystemExit, SignalException].freeze
|
|
52
52
|
|
|
53
|
+
# Placeholder emitted by #serialize_value_for_message in place of a value
|
|
54
|
+
# whose identifier or type matches the redaction configuration. This
|
|
55
|
+
# mirrors, for the human-readable log-probe message path, the
|
|
56
|
+
# notCapturedReason: "redactedIdent"/"redactedType" gating that
|
|
57
|
+
# #serialize_value applies on the snapshot path.
|
|
58
|
+
REDACTED_VALUE_FOR_MESSAGE = "[redacted]"
|
|
59
|
+
|
|
53
60
|
# Third-party library integration / custom serializers.
|
|
54
61
|
#
|
|
55
62
|
# Dynamic instrumentation has limited payload sizes, and for efficiency
|
|
@@ -375,9 +382,17 @@ module Datadog
|
|
|
375
382
|
#
|
|
376
383
|
# We also use the Ruby-like syntax for symbols, which don't exist
|
|
377
384
|
# in other languages.
|
|
378
|
-
|
|
385
|
+
#
|
|
386
|
+
# +name+, when given, is the identifier the template expression
|
|
387
|
+
# references at its top level; a redacted identifier yields the
|
|
388
|
+
# redaction placeholder, mirroring #serialize_value on the snapshot path.
|
|
389
|
+
def serialize_value_for_message(value, depth: 1, name: nil)
|
|
379
390
|
# This method is more verbose than "normal" Ruby code to avoid
|
|
380
391
|
# array allocations.
|
|
392
|
+
|
|
393
|
+
return REDACTED_VALUE_FOR_MESSAGE if redactor.redact_type?(value)
|
|
394
|
+
return REDACTED_VALUE_FOR_MESSAGE if name && redactor.redact_identifier?(name)
|
|
395
|
+
|
|
381
396
|
case value
|
|
382
397
|
when NilClass
|
|
383
398
|
"nil"
|
|
@@ -398,7 +413,7 @@ module Datadog
|
|
|
398
413
|
value = value_
|
|
399
414
|
end
|
|
400
415
|
"[" + value.map do |item|
|
|
401
|
-
serialize_value_for_message(item, depth - 1)
|
|
416
|
+
serialize_value_for_message(item, depth: depth - 1)
|
|
402
417
|
end.join(", ") + "]"
|
|
403
418
|
when Hash
|
|
404
419
|
return "..." if depth <= 0
|
|
@@ -413,7 +428,12 @@ module Datadog
|
|
|
413
428
|
truncated = true
|
|
414
429
|
end
|
|
415
430
|
serialized = keys.map do |key|
|
|
416
|
-
|
|
431
|
+
serialized_value = if (String === key || Symbol === key) && redactor.redact_identifier?(key)
|
|
432
|
+
REDACTED_VALUE_FOR_MESSAGE
|
|
433
|
+
else
|
|
434
|
+
serialize_value_for_message(value[key], depth: depth - 1)
|
|
435
|
+
end
|
|
436
|
+
"#{serialize_value_for_message(key, depth: depth - 1)} => #{serialized_value}"
|
|
417
437
|
end
|
|
418
438
|
if truncated
|
|
419
439
|
serialized[serialized.length] = serialized[serialized.length - 1]
|
|
@@ -435,7 +455,12 @@ module Datadog
|
|
|
435
455
|
serialized = vars.map do |var|
|
|
436
456
|
# +var+ here is always the instance variable name which is a
|
|
437
457
|
# symbol, we do not need to run it through our serializer.
|
|
438
|
-
|
|
458
|
+
serialized_value = if redactor.redact_identifier?(var)
|
|
459
|
+
REDACTED_VALUE_FOR_MESSAGE
|
|
460
|
+
else
|
|
461
|
+
serialize_value_for_message(value.send(:instance_variable_get, var), depth: depth - 1)
|
|
462
|
+
end
|
|
463
|
+
"#{var}=#{serialized_value}"
|
|
439
464
|
end
|
|
440
465
|
if truncated
|
|
441
466
|
serialized << serialized.last
|
|
@@ -154,7 +154,7 @@ module Datadog
|
|
|
154
154
|
attributes = {
|
|
155
155
|
"exception.type" => formatted_exception.type,
|
|
156
156
|
"exception.message" => formatted_exception.message,
|
|
157
|
-
"exception.stacktrace" => formatted_exception.backtrace
|
|
157
|
+
"exception.stacktrace" => formatted_exception.backtrace,
|
|
158
158
|
}
|
|
159
159
|
Datadog::Tracing::SpanEvent.new("exception", attributes: attributes)
|
|
160
160
|
end
|
|
@@ -19,7 +19,7 @@ module Datadog
|
|
|
19
19
|
TELEMETRY_METRICS_EVENTS_INTO_TYPES = {
|
|
20
20
|
LOGIN_SUCCESS_EVENT => "login_success",
|
|
21
21
|
LOGIN_FAILURE_EVENT => "login_failure",
|
|
22
|
-
SIGNUP_EVENT => "signup"
|
|
22
|
+
SIGNUP_EVENT => "signup",
|
|
23
23
|
}.freeze
|
|
24
24
|
|
|
25
25
|
class << self
|
|
@@ -241,7 +241,7 @@ module Datadog
|
|
|
241
241
|
|
|
242
242
|
tags = {
|
|
243
243
|
event_type: TELEMETRY_METRICS_EVENTS_INTO_TYPES[event],
|
|
244
|
-
sdk_version: TELEMETRY_METRICS_SDK_VERSION
|
|
244
|
+
sdk_version: TELEMETRY_METRICS_SDK_VERSION,
|
|
245
245
|
}
|
|
246
246
|
telemetry.inc(TELEMETRY_METRICS_NAMESPACE, TELEMETRY_METRICS_SDK_EVENT, 1, tags: tags)
|
|
247
247
|
end
|
|
@@ -23,18 +23,18 @@ module Datadog
|
|
|
23
23
|
{
|
|
24
24
|
timestamp: current_timestamp_ms,
|
|
25
25
|
allocation: {
|
|
26
|
-
key: result.allocation_key
|
|
26
|
+
key: result.allocation_key,
|
|
27
27
|
},
|
|
28
28
|
flag: {
|
|
29
|
-
key: flag_key
|
|
29
|
+
key: flag_key,
|
|
30
30
|
},
|
|
31
31
|
variant: {
|
|
32
|
-
key: result.variant
|
|
32
|
+
key: result.variant,
|
|
33
33
|
},
|
|
34
34
|
subject: {
|
|
35
35
|
id: context.targeting_key,
|
|
36
|
-
attributes: extract_attributes(context)
|
|
37
|
-
}
|
|
36
|
+
attributes: extract_attributes(context),
|
|
37
|
+
},
|
|
38
38
|
}.freeze
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -83,7 +83,7 @@ module Datadog
|
|
|
83
83
|
hostname: Datadog::Core::Environment::Platform.hostname,
|
|
84
84
|
kernel_name: Datadog::Core::Environment::Platform.kernel_name,
|
|
85
85
|
kernel_release: Datadog::Core::Environment::Platform.kernel_release,
|
|
86
|
-
kernel_version: Datadog::Core::Environment::Platform.kernel_version
|
|
86
|
+
kernel_version: Datadog::Core::Environment::Platform.kernel_version,
|
|
87
87
|
}.freeze
|
|
88
88
|
end
|
|
89
89
|
|
|
@@ -21,7 +21,8 @@ module Datadog
|
|
|
21
21
|
endpoint_collection_enabled:,
|
|
22
22
|
waiting_for_gvl_threshold_ns:,
|
|
23
23
|
otel_context_enabled:,
|
|
24
|
-
native_filenames_enabled
|
|
24
|
+
native_filenames_enabled:,
|
|
25
|
+
show_classes:
|
|
25
26
|
)
|
|
26
27
|
tracer_context_key = safely_extract_context_key_from(tracer)
|
|
27
28
|
self.class._native_initialize(
|
|
@@ -32,7 +33,8 @@ module Datadog
|
|
|
32
33
|
endpoint_collection_enabled: endpoint_collection_enabled,
|
|
33
34
|
waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
|
|
34
35
|
otel_context_enabled: otel_context_enabled,
|
|
35
|
-
native_filenames_enabled:
|
|
36
|
+
native_filenames_enabled: native_filenames_enabled,
|
|
37
|
+
show_classes: show_classes,
|
|
36
38
|
overhead_filename: __FILE__,
|
|
37
39
|
)
|
|
38
40
|
end
|
|
@@ -45,6 +47,7 @@ module Datadog
|
|
|
45
47
|
waiting_for_gvl_threshold_ns: 10_000_000,
|
|
46
48
|
otel_context_enabled: false,
|
|
47
49
|
native_filenames_enabled: true,
|
|
50
|
+
show_classes: false,
|
|
48
51
|
trigger_global_reset: true,
|
|
49
52
|
**options
|
|
50
53
|
)
|
|
@@ -56,6 +59,7 @@ module Datadog
|
|
|
56
59
|
waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
|
|
57
60
|
otel_context_enabled: otel_context_enabled,
|
|
58
61
|
native_filenames_enabled: native_filenames_enabled,
|
|
62
|
+
show_classes: show_classes,
|
|
59
63
|
**options,
|
|
60
64
|
)
|
|
61
65
|
|
|
@@ -90,17 +94,6 @@ module Datadog
|
|
|
90
94
|
context = provider.instance_variable_get(:@context)
|
|
91
95
|
context&.instance_variable_get(:@key)
|
|
92
96
|
end
|
|
93
|
-
|
|
94
|
-
def validate_native_filenames(native_filenames_enabled)
|
|
95
|
-
if native_filenames_enabled && !Datadog::Profiling::Collectors::Stack._native_filenames_available?
|
|
96
|
-
Datadog.logger.debug(
|
|
97
|
-
"Native filenames are enabled, but the required dladdr API was not available. Disabling native filenames."
|
|
98
|
-
)
|
|
99
|
-
false
|
|
100
|
-
else
|
|
101
|
-
native_filenames_enabled
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
97
|
end
|
|
105
98
|
end
|
|
106
99
|
end
|
|
@@ -105,6 +105,7 @@ module Datadog
|
|
|
105
105
|
waiting_for_gvl_threshold_ns: settings.profiling.advanced.waiting_for_gvl_threshold_ns,
|
|
106
106
|
otel_context_enabled: settings.profiling.advanced.preview_otel_context_enabled,
|
|
107
107
|
native_filenames_enabled: settings.profiling.advanced.native_filenames_enabled,
|
|
108
|
+
show_classes: settings.profiling.advanced.experimental_show_classes_enabled,
|
|
108
109
|
)
|
|
109
110
|
end
|
|
110
111
|
|
data/lib/datadog/profiling.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "rbconfig"
|
|
3
4
|
require_relative "core"
|
|
4
5
|
require_relative "core/environment/variable_helpers"
|
|
5
6
|
require_relative "core/utils/only_once"
|
|
@@ -7,6 +8,9 @@ require_relative "core/utils/only_once"
|
|
|
7
8
|
module Datadog
|
|
8
9
|
# Datadog Continuous Profiler implementation: https://docs.datadoghq.com/profiler/
|
|
9
10
|
module Profiling
|
|
11
|
+
STATIC_RUBY_PATH = (RbConfig::CONFIG["ENABLE_SHARED"] == "no") ? RbConfig.ruby.freeze : nil
|
|
12
|
+
private_constant :STATIC_RUBY_PATH
|
|
13
|
+
|
|
10
14
|
def self.supported?
|
|
11
15
|
unsupported_reason.nil?
|
|
12
16
|
end
|
|
@@ -616,7 +616,7 @@ module Datadog
|
|
|
616
616
|
language_specifics: {
|
|
617
617
|
visibility: method_visibility(klass, method_name),
|
|
618
618
|
method_type: method_type.to_s,
|
|
619
|
-
arity: method.arity
|
|
619
|
+
arity: method.arity,
|
|
620
620
|
},
|
|
621
621
|
symbols: extract_method_parameters(method)
|
|
622
622
|
)
|
|
@@ -647,7 +647,7 @@ module Datadog
|
|
|
647
647
|
# @param start_line [Integer] Fallback end_line if iseq unavailable
|
|
648
648
|
# @return [Array(Array<Hash>, Integer), Array(nil, Integer)]
|
|
649
649
|
def extract_targetable_lines(method, start_line)
|
|
650
|
-
iseq = RubyVM::InstructionSequence.of(method)
|
|
650
|
+
iseq = RubyVM::InstructionSequence.of(method)
|
|
651
651
|
unless iseq
|
|
652
652
|
@logger.debug { "symdb: no iseq for #{method.name} (C extension or native), skipping targetable lines" }
|
|
653
653
|
return [nil, start_line]
|
|
@@ -801,7 +801,7 @@ module Datadog
|
|
|
801
801
|
# objects allocated to read `source_location` are not retained between
|
|
802
802
|
# passes, so they can be GC'd as soon as the inner loop ends.
|
|
803
803
|
def collect_method_names_by_file(mod)
|
|
804
|
-
result = Hash.new { |h, k| h[k] = [] }
|
|
804
|
+
result = Hash.new { |h, k| h[k] = [] }
|
|
805
805
|
|
|
806
806
|
# Module#instance_methods(false) already returns both public and protected
|
|
807
807
|
# methods, so iterating it plus private_instance_methods covers all three
|
|
@@ -905,7 +905,7 @@ module Datadog
|
|
|
905
905
|
current[:children][part] ||= {
|
|
906
906
|
name: fqn, type: resolve_scope_type(fqn),
|
|
907
907
|
children: {}, methods: [], mod: nil,
|
|
908
|
-
source_file: file_path, fqn: fqn
|
|
908
|
+
source_file: file_path, fqn: fqn,
|
|
909
909
|
}
|
|
910
910
|
current = current[:children][part]
|
|
911
911
|
end
|
|
@@ -924,7 +924,7 @@ module Datadog
|
|
|
924
924
|
type: (Class === mod) ? "CLASS" : "MODULE",
|
|
925
925
|
children: {}, methods: [],
|
|
926
926
|
mod: mod, source_file: file_path,
|
|
927
|
-
fqn: mod_name
|
|
927
|
+
fqn: mod_name,
|
|
928
928
|
}
|
|
929
929
|
current[:children][leaf_name] = leaf
|
|
930
930
|
end
|
|
@@ -1043,7 +1043,7 @@ module Datadog
|
|
|
1043
1043
|
language_specifics: {
|
|
1044
1044
|
visibility: klass ? method_visibility(klass, method_name) : "public", # steep:ignore
|
|
1045
1045
|
method_type: "instance",
|
|
1046
|
-
arity: method.arity
|
|
1046
|
+
arity: method.arity,
|
|
1047
1047
|
},
|
|
1048
1048
|
symbols: extract_method_parameters(method)
|
|
1049
1049
|
)
|
|
@@ -104,9 +104,30 @@ module Datadog
|
|
|
104
104
|
return writer
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
if settings.tracing.native_transport && (transport = build_native_transport(agent_settings))
|
|
108
|
+
options = options.merge(transport: transport)
|
|
109
|
+
end
|
|
110
|
+
|
|
107
111
|
Tracing::Writer.new(agent_settings: agent_settings, **options)
|
|
108
112
|
end
|
|
109
113
|
|
|
114
|
+
def build_native_transport(agent_settings)
|
|
115
|
+
require_relative "transport/native"
|
|
116
|
+
|
|
117
|
+
unless Transport::Native.supported?
|
|
118
|
+
Datadog.logger.warn(
|
|
119
|
+
"Native transport requested but not available: #{Transport::Native::UNSUPPORTED_REASON}. " \
|
|
120
|
+
"Falling back to default HTTP transport."
|
|
121
|
+
)
|
|
122
|
+
return nil
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
Transport::Native::Transport.new(
|
|
126
|
+
agent_settings: agent_settings,
|
|
127
|
+
logger: Datadog.logger
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
|
|
110
131
|
def subscribe_to_writer_events!(writer, sampler_delegator, test_mode)
|
|
111
132
|
return unless writer.respond_to?(:events) # Check if it's a custom, external writer
|
|
112
133
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../../../core/telemetry/configuration_value"
|
|
4
|
+
|
|
3
5
|
module Datadog
|
|
4
6
|
module Tracing
|
|
5
7
|
module Configuration
|
|
@@ -56,6 +58,8 @@ module Datadog
|
|
|
56
58
|
precedence: Core::Configuration::Option::Precedence::REMOTE_CONFIGURATION
|
|
57
59
|
)
|
|
58
60
|
end
|
|
61
|
+
|
|
62
|
+
Core::Telemetry::ConfigurationValue.convert(value)
|
|
59
63
|
end
|
|
60
64
|
|
|
61
65
|
protected
|
|
@@ -24,11 +24,11 @@ module Datadog
|
|
|
24
24
|
def call(tracing_header_tags)
|
|
25
25
|
# Modify the remote configuration value that it matches the
|
|
26
26
|
# environment variable it configures.
|
|
27
|
-
tracing_header_tags&.map
|
|
27
|
+
parsed_header_tags = tracing_header_tags&.map do |hash|
|
|
28
28
|
"#{hash["header"]}:#{hash["tag_name"]}"
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
super
|
|
31
|
+
super(parsed_header_tags)
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -42,6 +42,7 @@ module Datadog
|
|
|
42
42
|
def call(tracing_sampling_rate)
|
|
43
43
|
super
|
|
44
44
|
Datadog.send(:components).reconfigure_sampler
|
|
45
|
+
tracing_sampling_rate
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
protected
|
|
@@ -78,8 +79,9 @@ module Datadog
|
|
|
78
79
|
tracing_sampling_rules = tracing_sampling_rules.to_json
|
|
79
80
|
end
|
|
80
81
|
|
|
81
|
-
super
|
|
82
|
+
telemetry_value = super
|
|
82
83
|
Datadog.send(:components).reconfigure_sampler
|
|
84
|
+
telemetry_value
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
protected
|
|
@@ -16,6 +16,7 @@ module Datadog
|
|
|
16
16
|
ENV_RESOURCE_RENAMING_ENABLED = "DD_TRACE_RESOURCE_RENAMING_ENABLED"
|
|
17
17
|
ENV_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT = "DD_TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT"
|
|
18
18
|
ENV_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED = "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"
|
|
19
|
+
ENV_EXPERIMENTAL_NATIVE_TRANSPORT_ENABLED = "DD_EXPERIMENTAL_NATIVE_TRANSPORT_ENABLED"
|
|
19
20
|
|
|
20
21
|
# @public_api
|
|
21
22
|
module SpanAttributeSchema
|
|
@@ -482,6 +482,22 @@ module Datadog
|
|
|
482
482
|
end
|
|
483
483
|
end
|
|
484
484
|
|
|
485
|
+
# Use the native trace transport (Rust via C FFI) instead of
|
|
486
|
+
# the default pure-Ruby HTTP transport.
|
|
487
|
+
#
|
|
488
|
+
# The native transport delegates serialization, stats
|
|
489
|
+
# computation, and HTTP sending to the Rust data pipeline.
|
|
490
|
+
#
|
|
491
|
+
# This option is recommended for internal use only.
|
|
492
|
+
#
|
|
493
|
+
# @default `false`
|
|
494
|
+
# @return [Boolean]
|
|
495
|
+
option :native_transport do |o|
|
|
496
|
+
o.env Configuration::Ext::ENV_EXPERIMENTAL_NATIVE_TRANSPORT_ENABLED
|
|
497
|
+
o.default false
|
|
498
|
+
o.type :bool
|
|
499
|
+
end
|
|
500
|
+
|
|
485
501
|
# A custom writer instance.
|
|
486
502
|
# The object must respect the {Datadog::Tracing::Writer} interface.
|
|
487
503
|
#
|