datadog 2.40.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 +85 -58
- data/ext/datadog_profiling_native_extension/collectors_stack.c +2 -2
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +26 -12
- data/ext/libdatadog_api/trace_exporter.c +409 -71
- 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 +10 -3
- data/lib/datadog/ai_guard/ext.rb +1 -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 +2 -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/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/rails/gateway/watcher.rb +2 -2
- 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/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/diagnostics/environment_logger.rb +36 -1
- 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/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 +127 -43
- data/lib/datadog/data_streams/processor.rb +14 -14
- data/lib/datadog/di/el/compiler.rb +23 -0
- data/lib/datadog/di/el/expression.rb +8 -5
- data/lib/datadog/di/instrumenter.rb +5 -4
- data/lib/datadog/di/probe_builder.rb +5 -4
- 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/tasks/exec.rb +1 -1
- data/lib/datadog/symbol_database/extractor.rb +6 -6
- data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +5 -3
- 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/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/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/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/transport/io/traces.rb +1 -1
- data/lib/datadog/tracing/transport/native.rb +78 -54
- data/lib/datadog/tracing/writer.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +6 -5
|
@@ -185,7 +185,7 @@ module Datadog
|
|
|
185
185
|
is_agent: false,
|
|
186
186
|
client_tracer: client_tracer,
|
|
187
187
|
# base64 is needed otherwise the Go agent fails with an unmarshal error
|
|
188
|
-
capabilities: @capabilities.base64_capabilities
|
|
188
|
+
capabilities: @capabilities.base64_capabilities,
|
|
189
189
|
},
|
|
190
190
|
cached_target_files: state.cached_target_files,
|
|
191
191
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module Core
|
|
5
|
+
module Telemetry
|
|
6
|
+
module ConfigurationValue
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def convert(value)
|
|
10
|
+
case value
|
|
11
|
+
when Integer, String, true, false, nil
|
|
12
|
+
value
|
|
13
|
+
when Float
|
|
14
|
+
value.finite? ? value : value.to_s
|
|
15
|
+
when Hash
|
|
16
|
+
value.map { |key, entry_value| "#{key}:#{entry_value}" }.join(",")
|
|
17
|
+
when Array
|
|
18
|
+
value.join(",")
|
|
19
|
+
when Module
|
|
20
|
+
value.name.to_s
|
|
21
|
+
else
|
|
22
|
+
implements_to_s = begin
|
|
23
|
+
value.method(:to_s).owner != Kernel
|
|
24
|
+
rescue NameError
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if implements_to_s
|
|
29
|
+
value.to_s
|
|
30
|
+
else
|
|
31
|
+
value.class.to_s
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "base"
|
|
4
|
+
require_relative "../configuration_value"
|
|
4
5
|
|
|
5
6
|
module Datadog
|
|
6
7
|
module Core
|
|
@@ -27,10 +28,11 @@ module Datadog
|
|
|
27
28
|
def configuration
|
|
28
29
|
config = Datadog.configuration
|
|
29
30
|
|
|
31
|
+
# @type var res: Array[telemetry_configuration]
|
|
30
32
|
res = @changes.map do |name, value|
|
|
31
33
|
{
|
|
32
34
|
name: name,
|
|
33
|
-
value: value,
|
|
35
|
+
value: Telemetry::ConfigurationValue.convert(value),
|
|
34
36
|
origin: @origin,
|
|
35
37
|
seq_id: Configuration::Option::Precedence::REMOTE_CONFIGURATION.numeric.next,
|
|
36
38
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "base"
|
|
4
|
+
require_relative "../configuration_value"
|
|
4
5
|
|
|
5
6
|
module Datadog
|
|
6
7
|
module Core
|
|
@@ -65,7 +66,7 @@ module Datadog
|
|
|
65
66
|
# actually enabled by env var or by implicit enablement via
|
|
66
67
|
# remote config.
|
|
67
68
|
enabled: components.dynamic_instrumentation&.started? || false,
|
|
68
|
-
}
|
|
69
|
+
},
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
if (unsupported_reason = Datadog::Profiling.unsupported_reason)
|
|
@@ -214,23 +215,9 @@ module Datadog
|
|
|
214
215
|
end
|
|
215
216
|
|
|
216
217
|
def to_telemetry_value(value)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
value
|
|
221
|
-
when Hash
|
|
222
|
-
value.map { |key, entry_value| "#{key}:#{entry_value}" }.join(",")
|
|
223
|
-
when Array
|
|
224
|
-
value.join(",")
|
|
225
|
-
when Module
|
|
226
|
-
value.name.to_s
|
|
227
|
-
else
|
|
228
|
-
if implements_to_s?(value)
|
|
229
|
-
value.to_s
|
|
230
|
-
else
|
|
231
|
-
value.class.to_s
|
|
232
|
-
end
|
|
233
|
-
end
|
|
218
|
+
return value.to_s if value.is_a?(Float)
|
|
219
|
+
|
|
220
|
+
Telemetry::ConfigurationValue.convert(value)
|
|
234
221
|
end
|
|
235
222
|
|
|
236
223
|
def install_signature(settings)
|
|
@@ -280,12 +267,6 @@ module Datadog
|
|
|
280
267
|
parent_setting = settings.dig(*split_option)
|
|
281
268
|
parent_setting.send(:resolve_option, option_name.to_sym)
|
|
282
269
|
end
|
|
283
|
-
|
|
284
|
-
def implements_to_s?(value)
|
|
285
|
-
value.method(:to_s).owner != Kernel
|
|
286
|
-
rescue NameError
|
|
287
|
-
false
|
|
288
|
-
end
|
|
289
270
|
end
|
|
290
271
|
end
|
|
291
272
|
end
|
|
@@ -37,7 +37,7 @@ module Datadog
|
|
|
37
37
|
points: values,
|
|
38
38
|
type: type,
|
|
39
39
|
tags: tags,
|
|
40
|
-
common: common
|
|
40
|
+
common: common,
|
|
41
41
|
}
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -179,7 +179,7 @@ module Datadog
|
|
|
179
179
|
metric: name,
|
|
180
180
|
points: values,
|
|
181
181
|
tags: tags,
|
|
182
|
-
common: common
|
|
182
|
+
common: common,
|
|
183
183
|
}
|
|
184
184
|
end
|
|
185
185
|
end
|
|
@@ -50,7 +50,7 @@ module Datadog
|
|
|
50
50
|
runtime_version: Core::Environment::Ext::ENGINE_VERSION,
|
|
51
51
|
service_name: config.service,
|
|
52
52
|
service_version: config.version,
|
|
53
|
-
tracer_version: tracer_version
|
|
53
|
+
tracer_version: tracer_version,
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
tag_process_tags!(app, config)
|
|
@@ -64,7 +64,7 @@ module Datadog
|
|
|
64
64
|
hostname: Core::Environment::Platform.hostname,
|
|
65
65
|
kernel_name: Core::Environment::Platform.kernel_name,
|
|
66
66
|
kernel_release: Core::Environment::Platform.kernel_release,
|
|
67
|
-
kernel_version: Core::Environment::Platform.kernel_version
|
|
67
|
+
kernel_version: Core::Environment::Platform.kernel_version,
|
|
68
68
|
}
|
|
69
69
|
end
|
|
70
70
|
|
|
@@ -61,7 +61,7 @@ module Datadog
|
|
|
61
61
|
Core::Transport::Ext::HTTP::HEADER_META_LANG_INTERPRETER_VENDOR =>
|
|
62
62
|
Core::Environment::Ext::LANG_ENGINE,
|
|
63
63
|
Core::Transport::Ext::HTTP::HEADER_META_TRACER_VERSION =>
|
|
64
|
-
Datadog::Core::Environment::Ext::GEM_DATADOG_VERSION
|
|
64
|
+
Datadog::Core::Environment::Ext::GEM_DATADOG_VERSION,
|
|
65
65
|
}.tap do |headers|
|
|
66
66
|
# Add application container info
|
|
67
67
|
headers.merge!(Core::Environment::Container.to_headers)
|
|
@@ -69,7 +69,7 @@ module Datadog
|
|
|
69
69
|
|
|
70
70
|
@current_api_id = api_id
|
|
71
71
|
client_class = self.class.http_client_class || Core::Transport::HTTP::Client
|
|
72
|
-
@client = client_class.new(current_api, logger: logger)
|
|
72
|
+
@client = client_class.new(current_api, logger: logger)
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def downgrade?(response)
|
|
@@ -6,14 +6,30 @@ module Datadog
|
|
|
6
6
|
# Monkey patches `Kernel#fork` and similar functions, adding an `at_fork` callback mechanism which
|
|
7
7
|
# is used to restart observability after the VM forks (e.g. in multiprocess Ruby apps).
|
|
8
8
|
module AtForkMonkeyPatch
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
class Callback
|
|
10
|
+
attr_reader :block, :group
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
def initialize(block, group = nil)
|
|
13
|
+
@block = block
|
|
14
|
+
@group = group
|
|
15
|
+
freeze
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
private_constant :Callback
|
|
19
|
+
|
|
20
|
+
EMPTY_AT_FORK_BLOCKS = {
|
|
21
|
+
before: [].freeze,
|
|
22
|
+
parent: [].freeze,
|
|
23
|
+
child: [].freeze,
|
|
24
|
+
}.freeze
|
|
25
|
+
private_constant :EMPTY_AT_FORK_BLOCKS
|
|
26
|
+
|
|
27
|
+
@at_fork_blocks = EMPTY_AT_FORK_BLOCKS
|
|
14
28
|
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
# Serializes copy-on-write registry updates. Fork dispatch only reads the
|
|
30
|
+
# latest immutable registry reference and never acquires this mutex.
|
|
31
|
+
AT_FORK_REGISTRY_MUTEX = Mutex.new
|
|
32
|
+
private_constant :AT_FORK_REGISTRY_MUTEX
|
|
17
33
|
|
|
18
34
|
def self.supported?
|
|
19
35
|
Process.respond_to?(:fork)
|
|
@@ -37,9 +53,38 @@ module Datadog
|
|
|
37
53
|
true
|
|
38
54
|
end
|
|
39
55
|
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
# Runs the callbacks copied for one fork lifecycle. Before callbacks
|
|
57
|
+
# stop at the first failure; parent and child callbacks all run before
|
|
58
|
+
# the first failure is re-raised.
|
|
59
|
+
def self.run_at_fork_blocks(stage, snapshot:, started: nil)
|
|
60
|
+
callbacks = blocks_for(snapshot, stage)
|
|
61
|
+
if stage == :before
|
|
62
|
+
return callbacks.each do |callback|
|
|
63
|
+
started[callback.group] = true if started && callback.group
|
|
64
|
+
callback.block.call
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
error = nil
|
|
69
|
+
callbacks.each do |callback|
|
|
70
|
+
next if started && callback.group && !started.key?(callback.group)
|
|
71
|
+
|
|
72
|
+
callback.block.call
|
|
73
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- finish cleanup, then re-raise the first failure
|
|
74
|
+
error ||= e
|
|
75
|
+
end
|
|
76
|
+
raise error if error
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.run_parent_cleanup(snapshot, started, fork_error)
|
|
80
|
+
run_at_fork_blocks(:parent, snapshot: snapshot, started: started)
|
|
81
|
+
rescue Exception => cleanup_error # rubocop:disable Lint/RescueException -- preserve the original fork failure
|
|
82
|
+
Datadog.logger.warn do
|
|
83
|
+
"Parent at-fork cleanup failed while handling #{fork_error.class}: " \
|
|
84
|
+
"#{cleanup_error.class}: #{cleanup_error.message}"
|
|
85
|
+
end
|
|
42
86
|
end
|
|
87
|
+
private_class_method :run_parent_cleanup
|
|
43
88
|
|
|
44
89
|
# Registers a block to run at the given fork +stage+ (+:before+,
|
|
45
90
|
# +:parent+, or +:child+).
|
|
@@ -49,26 +94,63 @@ module Datadog
|
|
|
49
94
|
def self.at_fork(stage, &block)
|
|
50
95
|
raise(ArgumentError, "Missing block argument") unless block
|
|
51
96
|
|
|
52
|
-
|
|
97
|
+
AT_FORK_REGISTRY_MUTEX.synchronize do
|
|
98
|
+
current = @at_fork_blocks
|
|
99
|
+
@at_fork_blocks = current.merge(
|
|
100
|
+
stage => (blocks_for(current, stage) + [Callback.new(block)]).freeze
|
|
101
|
+
).freeze
|
|
102
|
+
end
|
|
53
103
|
|
|
54
104
|
block
|
|
55
105
|
end
|
|
56
106
|
|
|
107
|
+
# Registers one before/parent/child callback triplet atomically relative
|
|
108
|
+
# to the snapshots taken by fork dispatch.
|
|
109
|
+
def self.at_fork_blocks(before:, parent:, child:)
|
|
110
|
+
blocks = {before: before, parent: parent, child: child}
|
|
111
|
+
group = Object.new.freeze
|
|
112
|
+
AT_FORK_REGISTRY_MUTEX.synchronize do
|
|
113
|
+
current = @at_fork_blocks
|
|
114
|
+
@at_fork_blocks = {
|
|
115
|
+
before: (current.fetch(:before) + [Callback.new(before, group)]).freeze,
|
|
116
|
+
parent: (current.fetch(:parent) + [Callback.new(parent, group)]).freeze,
|
|
117
|
+
child: (current.fetch(:child) + [Callback.new(child, group)]).freeze,
|
|
118
|
+
}.freeze
|
|
119
|
+
end
|
|
120
|
+
blocks
|
|
121
|
+
end
|
|
122
|
+
|
|
57
123
|
# Deregisters a block previously registered with {.at_fork} for the given
|
|
58
124
|
# +stage+. It is a no-op (does not raise) when +block+ was never
|
|
59
125
|
# registered (or was already removed). Raises +ArgumentError+ for an
|
|
60
126
|
# unknown stage, matching the {.at_fork} contract.
|
|
61
127
|
def self.remove_at_fork(stage, block)
|
|
62
|
-
|
|
128
|
+
AT_FORK_REGISTRY_MUTEX.synchronize do
|
|
129
|
+
current = @at_fork_blocks
|
|
130
|
+
callbacks = blocks_for(current, stage)
|
|
131
|
+
@at_fork_blocks = current.merge(
|
|
132
|
+
stage => callbacks.reject { |callback| callback.block.equal?(block) }.freeze
|
|
133
|
+
).freeze
|
|
134
|
+
end
|
|
63
135
|
|
|
64
136
|
nil
|
|
65
137
|
end
|
|
66
138
|
|
|
67
|
-
|
|
139
|
+
# Returns the immutable callback registry for one fork lifecycle.
|
|
140
|
+
# Copy-on-write updates publish a new reference, so registrations made
|
|
141
|
+
# afterwards apply only to the next lifecycle without locking this read.
|
|
142
|
+
def self.snapshot_at_fork_blocks
|
|
143
|
+
@at_fork_blocks
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.replace_at_fork_blocks(snapshot)
|
|
147
|
+
AT_FORK_REGISTRY_MUTEX.synchronize { @at_fork_blocks = snapshot }
|
|
148
|
+
end
|
|
149
|
+
private_class_method :replace_at_fork_blocks
|
|
150
|
+
|
|
151
|
+
def self.blocks_for(snapshot, stage)
|
|
68
152
|
case stage
|
|
69
|
-
when :before then
|
|
70
|
-
when :parent then AT_FORK_PARENT_BLOCKS
|
|
71
|
-
when :child then AT_FORK_CHILD_BLOCKS
|
|
153
|
+
when :before, :parent, :child then snapshot.fetch(stage)
|
|
72
154
|
else raise(ArgumentError, "Unsupported stage #{stage}")
|
|
73
155
|
end
|
|
74
156
|
end
|
|
@@ -77,27 +159,29 @@ module Datadog
|
|
|
77
159
|
# Adds `at_fork` behavior; see parent module for details.
|
|
78
160
|
module KernelMonkeyPatch
|
|
79
161
|
def fork
|
|
162
|
+
snapshot = AtForkMonkeyPatch.snapshot_at_fork_blocks
|
|
163
|
+
started = {}
|
|
164
|
+
|
|
80
165
|
# If a block is provided, it must be wrapped to trigger callbacks.
|
|
81
166
|
child_block = if block_given?
|
|
82
167
|
proc do
|
|
83
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:child)
|
|
168
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:child, snapshot: snapshot)
|
|
84
169
|
|
|
85
170
|
# Invoke original block
|
|
86
171
|
yield
|
|
87
172
|
end
|
|
88
173
|
end
|
|
89
174
|
|
|
90
|
-
# Run pre-fork callbacks in the parent, just before forking.
|
|
91
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:before)
|
|
92
|
-
|
|
93
|
-
# Start fork
|
|
94
|
-
# If a block is provided, use the wrapped version.
|
|
95
175
|
begin
|
|
176
|
+
# Run pre-fork callbacks in the parent, just before forking.
|
|
177
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:before, snapshot: snapshot, started: started)
|
|
178
|
+
|
|
179
|
+
# Start fork. If a block is provided, use the wrapped version.
|
|
96
180
|
result = child_block.nil? ? super : super(&child_block)
|
|
97
|
-
rescue Exception # rubocop:disable Lint/RescueException -- re-raised unchanged; we only need to run parent cleanup first
|
|
98
|
-
# The fork failed and we are still in
|
|
99
|
-
#
|
|
100
|
-
AtForkMonkeyPatch.
|
|
181
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- re-raised unchanged; we only need to run parent cleanup first
|
|
182
|
+
# The fork or a before-fork callback failed and we are still in
|
|
183
|
+
# the parent. Restore any state set up by earlier callbacks.
|
|
184
|
+
AtForkMonkeyPatch.send(:run_parent_cleanup, snapshot, started, e)
|
|
101
185
|
raise
|
|
102
186
|
end
|
|
103
187
|
|
|
@@ -106,9 +190,9 @@ module Datadog
|
|
|
106
190
|
# If we're in the parent, result = pid: trigger parent callbacks.
|
|
107
191
|
# (If it gets called with a block, it only returns on the parent)
|
|
108
192
|
if result.nil?
|
|
109
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:child)
|
|
193
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:child, snapshot: snapshot)
|
|
110
194
|
else
|
|
111
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:parent)
|
|
195
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:parent, snapshot: snapshot)
|
|
112
196
|
end
|
|
113
197
|
|
|
114
198
|
result
|
|
@@ -120,23 +204,22 @@ module Datadog
|
|
|
120
204
|
# Hook provided by Ruby 3.1+ for observability libraries that want to know about fork, see
|
|
121
205
|
# https://github.com/ruby/ruby/pull/5017 and https://bugs.ruby-lang.org/issues/17795
|
|
122
206
|
def _fork
|
|
123
|
-
AtForkMonkeyPatch.
|
|
124
|
-
|
|
207
|
+
snapshot = AtForkMonkeyPatch.snapshot_at_fork_blocks
|
|
208
|
+
started = {}
|
|
125
209
|
begin
|
|
210
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:before, snapshot: snapshot, started: started)
|
|
126
211
|
pid = super
|
|
127
|
-
rescue Exception # rubocop:disable Lint/RescueException -- re-raised unchanged; we only need to run parent cleanup first
|
|
128
|
-
# The fork failed, so no child was
|
|
129
|
-
#
|
|
130
|
-
|
|
131
|
-
# restored, then re-raise.
|
|
132
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:parent)
|
|
212
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- re-raised unchanged; we only need to run parent cleanup first
|
|
213
|
+
# The fork or a before-fork callback failed, so no child was
|
|
214
|
+
# created. Restore state set up by any earlier callbacks.
|
|
215
|
+
AtForkMonkeyPatch.send(:run_parent_cleanup, snapshot, started, e)
|
|
133
216
|
raise
|
|
134
217
|
end
|
|
135
218
|
|
|
136
219
|
if pid == 0
|
|
137
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:child)
|
|
220
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:child, snapshot: snapshot)
|
|
138
221
|
else
|
|
139
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:parent)
|
|
222
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:parent, snapshot: snapshot)
|
|
140
223
|
end
|
|
141
224
|
|
|
142
225
|
pid
|
|
@@ -146,20 +229,21 @@ module Datadog
|
|
|
146
229
|
# keeps executing code in the child process, killing off the parent, thus effectively replacing it.
|
|
147
230
|
# This is not covered by `_fork` and thus we have some extra code for it.
|
|
148
231
|
def daemon(*args)
|
|
149
|
-
AtForkMonkeyPatch.
|
|
150
|
-
|
|
232
|
+
snapshot = AtForkMonkeyPatch.snapshot_at_fork_blocks
|
|
233
|
+
started = {}
|
|
151
234
|
begin
|
|
235
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:before, snapshot: snapshot, started: started)
|
|
152
236
|
result = super
|
|
153
|
-
rescue Exception # rubocop:disable Lint/RescueException -- re-raised unchanged; we only need to run parent cleanup first
|
|
154
|
-
# `daemon` failed, so the original
|
|
155
|
-
#
|
|
156
|
-
AtForkMonkeyPatch.
|
|
237
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- re-raised unchanged; we only need to run parent cleanup first
|
|
238
|
+
# `daemon` or a before-fork callback failed, so the original
|
|
239
|
+
# process survives. Restore state set up by earlier callbacks.
|
|
240
|
+
AtForkMonkeyPatch.send(:run_parent_cleanup, snapshot, started, e)
|
|
157
241
|
raise
|
|
158
242
|
end
|
|
159
243
|
|
|
160
244
|
# `daemon` kills the parent, so there is no surviving parent to run
|
|
161
245
|
# `:parent` callbacks in; only the child continues executing.
|
|
162
|
-
AtForkMonkeyPatch.run_at_fork_blocks(:child)
|
|
246
|
+
AtForkMonkeyPatch.run_at_fork_blocks(:child, snapshot: snapshot)
|
|
163
247
|
|
|
164
248
|
result
|
|
165
249
|
end
|
|
@@ -79,7 +79,7 @@ module Datadog
|
|
|
79
79
|
topic: topic,
|
|
80
80
|
partition: partition,
|
|
81
81
|
offset: offset,
|
|
82
|
-
timestamp_ns: (now.to_f * 1e9).to_i
|
|
82
|
+
timestamp_ns: (now.to_f * 1e9).to_i,
|
|
83
83
|
}
|
|
84
84
|
)
|
|
85
85
|
true
|
|
@@ -98,7 +98,7 @@ module Datadog
|
|
|
98
98
|
topic: topic,
|
|
99
99
|
partition: partition,
|
|
100
100
|
offset: offset,
|
|
101
|
-
timestamp: now
|
|
101
|
+
timestamp: now,
|
|
102
102
|
}
|
|
103
103
|
)
|
|
104
104
|
true
|
|
@@ -186,7 +186,7 @@ module Datadog
|
|
|
186
186
|
|
|
187
187
|
bucket[:latest_produce_offsets][partition_key] = [
|
|
188
188
|
event[:offset],
|
|
189
|
-
bucket[:latest_produce_offsets][partition_key] || 0
|
|
189
|
+
bucket[:latest_produce_offsets][partition_key] || 0,
|
|
190
190
|
].max
|
|
191
191
|
end
|
|
192
192
|
|
|
@@ -196,7 +196,7 @@ module Datadog
|
|
|
196
196
|
partition: event[:partition],
|
|
197
197
|
offset: event[:offset],
|
|
198
198
|
timestamp: event[:timestamp],
|
|
199
|
-
timestamp_sec: event[:timestamp].to_f
|
|
199
|
+
timestamp_sec: event[:timestamp].to_f,
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
timestamp_ns = (event[:timestamp].to_f * 1e9).to_i
|
|
@@ -216,7 +216,7 @@ module Datadog
|
|
|
216
216
|
expected_offset: previous_offset + 1,
|
|
217
217
|
actual_offset: event[:offset],
|
|
218
218
|
gap_size: event[:offset] - previous_offset - 1,
|
|
219
|
-
timestamp_sec: event[:timestamp].to_f
|
|
219
|
+
timestamp_sec: event[:timestamp].to_f,
|
|
220
220
|
}
|
|
221
221
|
end
|
|
222
222
|
|
|
@@ -321,7 +321,7 @@ module Datadog
|
|
|
321
321
|
"TracerVersion" => Datadog::VERSION::STRING,
|
|
322
322
|
"Lang" => "ruby",
|
|
323
323
|
"Stats" => stats_buckets,
|
|
324
|
-
"Hostname" => hostname
|
|
324
|
+
"Hostname" => hostname,
|
|
325
325
|
} # : ::Hash[::String, (::String | ::Array[::String])]
|
|
326
326
|
|
|
327
327
|
payload["ProcessTags"] = Core::Environment::Process.tags if @settings.experimental_propagate_process_tags_enabled
|
|
@@ -400,7 +400,7 @@ module Datadog
|
|
|
400
400
|
full_pathway_latency_sec: full_pathway_latency_sec,
|
|
401
401
|
payload_size: payload_size,
|
|
402
402
|
tags: tags,
|
|
403
|
-
timestamp_sec: timestamp_sec
|
|
403
|
+
timestamp_sec: timestamp_sec,
|
|
404
404
|
}
|
|
405
405
|
)
|
|
406
406
|
true
|
|
@@ -449,14 +449,14 @@ module Datadog
|
|
|
449
449
|
topic, partition = key.split(":", 2)
|
|
450
450
|
backlogs << {
|
|
451
451
|
"Tags" => ["type:kafka_produce", "topic:#{topic}", "partition:#{partition}"],
|
|
452
|
-
"Value" => offset
|
|
452
|
+
"Value" => offset,
|
|
453
453
|
}
|
|
454
454
|
end
|
|
455
455
|
bucket[:latest_commit_offsets].each do |key, offset|
|
|
456
456
|
group, topic, partition = key.split(":", 3)
|
|
457
457
|
backlogs << {
|
|
458
458
|
"Tags" => ["type:kafka_commit", "consumer_group:#{group}", "topic:#{topic}", "partition:#{partition}"],
|
|
459
|
-
"Value" => offset
|
|
459
|
+
"Value" => offset,
|
|
460
460
|
}
|
|
461
461
|
end
|
|
462
462
|
|
|
@@ -464,7 +464,7 @@ module Datadog
|
|
|
464
464
|
"Start" => bucket_time_ns,
|
|
465
465
|
"Duration" => @bucket_size_ns,
|
|
466
466
|
"Stats" => bucket_stats,
|
|
467
|
-
"Backlogs" => backlogs + serialize_consumer_backlogs
|
|
467
|
+
"Backlogs" => backlogs + serialize_consumer_backlogs,
|
|
468
468
|
}
|
|
469
469
|
end
|
|
470
470
|
|
|
@@ -479,9 +479,9 @@ module Datadog
|
|
|
479
479
|
"Tags" => [
|
|
480
480
|
"type:kafka_commit",
|
|
481
481
|
"topic:#{stat[:topic]}",
|
|
482
|
-
"partition:#{stat[:partition]}"
|
|
482
|
+
"partition:#{stat[:partition]}",
|
|
483
483
|
],
|
|
484
|
-
"Value" => stat[:offset]
|
|
484
|
+
"Value" => stat[:offset],
|
|
485
485
|
}
|
|
486
486
|
end
|
|
487
487
|
end
|
|
@@ -494,7 +494,7 @@ module Datadog
|
|
|
494
494
|
{
|
|
495
495
|
pathway_stats: {},
|
|
496
496
|
latest_produce_offsets: {},
|
|
497
|
-
latest_commit_offsets: {}
|
|
497
|
+
latest_commit_offsets: {},
|
|
498
498
|
}
|
|
499
499
|
end
|
|
500
500
|
|
|
@@ -503,7 +503,7 @@ module Datadog
|
|
|
503
503
|
edge_latency: Datadog::Core::DDSketch.new,
|
|
504
504
|
full_pathway_latency: Datadog::Core::DDSketch.new,
|
|
505
505
|
payload_size_sum: 0,
|
|
506
|
-
payload_size_count: 0
|
|
506
|
+
payload_size_count: 0,
|
|
507
507
|
}
|
|
508
508
|
end
|
|
509
509
|
end
|
|
@@ -31,6 +31,29 @@ module Datadog
|
|
|
31
31
|
[code, regexps]
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
# Returns the identifier that +ast+ directly references at its top
|
|
35
|
+
# level, so the message path can redact direct references the same
|
|
36
|
+
# way snapshots redact by name.
|
|
37
|
+
#
|
|
38
|
+
# @param ast [untyped] top-level expression AST from a probe definition.
|
|
39
|
+
# @return [String, nil] the variable name for a `ref`/`iref`, the field
|
|
40
|
+
# name for a `getmember`, or the string key for an `index`; nil when
|
|
41
|
+
# the top-level expression is not a direct reference.
|
|
42
|
+
def redaction_identifier(ast)
|
|
43
|
+
return nil unless Hash === ast && ast.length == 1
|
|
44
|
+
|
|
45
|
+
entry = ast.first
|
|
46
|
+
return nil if entry.nil?
|
|
47
|
+
|
|
48
|
+
op, target = entry
|
|
49
|
+
case op
|
|
50
|
+
when "ref"
|
|
51
|
+
target if String === target
|
|
52
|
+
when "getmember", "index"
|
|
53
|
+
target[1] if Array === target && target.length == 2 && String === target[1]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
34
57
|
private
|
|
35
58
|
|
|
36
59
|
# Steep: https://github.com/soutaro/steep/issues/363
|
|
@@ -12,12 +12,17 @@ module Datadog
|
|
|
12
12
|
# @param regexps [Array<Regexp>] precompiled `matches` regexps (see
|
|
13
13
|
# Compiler#precompile_regexp), the second element returned by
|
|
14
14
|
# Compiler#compile.
|
|
15
|
-
|
|
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)
|
|
16
20
|
unless String === compiled_expr
|
|
17
21
|
raise ArgumentError, "compiled_expr must be a string"
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
@dsl_expr = dsl_expr
|
|
25
|
+
@redaction_identifier = redaction_identifier
|
|
21
26
|
|
|
22
27
|
cls = Class.new(Evaluator)
|
|
23
28
|
cls.class_exec do
|
|
@@ -28,14 +33,12 @@ module Datadog
|
|
|
28
33
|
end
|
|
29
34
|
RUBY
|
|
30
35
|
end
|
|
31
|
-
|
|
32
|
-
# Class#new as () -> untyped and cannot see that initializer
|
|
33
|
-
# through this dynamically created subclass.
|
|
34
|
-
@evaluator = cls.new(regexps) # steep:ignore UnexpectedPositionalArgument
|
|
36
|
+
@evaluator = cls.new(regexps)
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
attr_reader :dsl_expr
|
|
38
40
|
attr_reader :evaluator
|
|
41
|
+
attr_reader :redaction_identifier
|
|
39
42
|
|
|
40
43
|
def evaluate(context)
|
|
41
44
|
@evaluator.evaluate(context)
|