datadog 2.40.0 → 2.42.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 +120 -59
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +12 -24
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +110 -61
- data/ext/datadog_profiling_native_extension/collectors_stack.c +13 -5
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +141 -103
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +7 -3
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -10
- data/ext/datadog_profiling_native_extension/extconf.rb +52 -93
- data/ext/datadog_profiling_native_extension/heap_recorder.c +338 -255
- data/ext/datadog_profiling_native_extension/heap_recorder.h +46 -31
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -27
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +526 -443
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +15 -3
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -79
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +0 -7
- data/ext/datadog_profiling_native_extension/stack_recorder.c +93 -61
- data/ext/datadog_profiling_native_extension/stack_recorder.h +12 -4
- data/ext/libdatadog_api/datadog_ruby_common.h +0 -10
- data/ext/libdatadog_api/di.c +10 -0
- data/ext/libdatadog_api/extconf.rb +3 -0
- data/ext/libdatadog_api/init.c +2 -0
- data/ext/libdatadog_api/otel_thread_context.c +232 -0
- data/ext/libdatadog_api/otel_thread_context.h +5 -0
- 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/assets/blocked.html +1 -108
- 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 +3 -2
- data/lib/datadog/core/configuration/option_definition.rb +1 -1
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/crashtracking/component.rb +5 -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/pathway_context.rb +20 -22
- data/lib/datadog/data_streams/processor.rb +45 -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 +46 -5
- data/lib/datadog/di/logger.rb +2 -2
- data/lib/datadog/di/probe.rb +9 -1
- data/lib/datadog/di/probe_builder.rb +5 -4
- data/lib/datadog/di/probe_notification_builder.rb +3 -2
- data/lib/datadog/di/remote.rb +3 -3
- 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/evaluation_engine.rb +29 -3
- data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
- data/lib/datadog/open_feature/exposures/event.rb +15 -8
- data/lib/datadog/open_feature/ext.rb +19 -0
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +236 -80
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +179 -68
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +24 -21
- data/lib/datadog/open_feature/native_evaluator.rb +33 -6
- data/lib/datadog/open_feature/noop_evaluator.rb +5 -0
- data/lib/datadog/open_feature/provider.rb +11 -2
- data/lib/datadog/opentelemetry/sdk/propagator.rb +1 -1
- data/lib/datadog/opentelemetry/trace.rb +3 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -0
- data/lib/datadog/profiling/collectors/info.rb +1 -1
- data/lib/datadog/profiling/collectors/thread_context.rb +0 -4
- data/lib/datadog/profiling/component.rb +8 -16
- 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/sql.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/services.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/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 -3
- data/lib/datadog/tracing/distributed/datadog.rb +3 -3
- data/lib/datadog/tracing/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +14 -271
- data/lib/datadog/tracing/distributed/trace_state/datadog.rb +233 -0
- data/lib/datadog/tracing/distributed/trace_state/ext.rb +44 -0
- data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +156 -0
- data/lib/datadog/tracing/distributed/trace_state.rb +121 -0
- data/lib/datadog/tracing/metadata/tagging.rb +1 -1
- data/lib/datadog/tracing/otel_thread_context.rb +30 -0
- data/lib/datadog/tracing/remote.rb +197 -29
- data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
- data/lib/datadog/tracing/span.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/trace_digest.rb +22 -4
- data/lib/datadog/tracing/trace_operation.rb +22 -10
- data/lib/datadog/tracing/tracer.rb +5 -5
- 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 +15 -8
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -69
|
@@ -44,7 +44,11 @@ module Datadog
|
|
|
44
44
|
# Reports unhandled exceptions to the crash tracker if available and appropriate.
|
|
45
45
|
# This is called from the at_exit hook to report unhandled exceptions.
|
|
46
46
|
def self.report_unhandled_exception(exception)
|
|
47
|
-
return unless exception &&
|
|
47
|
+
return unless exception &&
|
|
48
|
+
!exception.is_a?(SystemExit) &&
|
|
49
|
+
!exception.is_a?(SignalException) &&
|
|
50
|
+
!exception.is_a?(NoMemoryError) &&
|
|
51
|
+
!exception.is_a?(SystemStackError)
|
|
48
52
|
|
|
49
53
|
begin
|
|
50
54
|
crashtracker = Datadog.send(:components, allow_initialization: false)&.crashtracker
|
|
@@ -75,7 +75,10 @@ module Datadog
|
|
|
75
75
|
tags: tags,
|
|
76
76
|
runtime_metrics_enabled: runtime_metrics_enabled,
|
|
77
77
|
vm: vm,
|
|
78
|
-
health_metrics_enabled: health_metrics_enabled
|
|
78
|
+
health_metrics_enabled: health_metrics_enabled,
|
|
79
|
+
otlp_traces_export_enabled: otlp_traces_export_enabled,
|
|
80
|
+
otlp_metrics_export_enabled: otlp_metrics_export_enabled,
|
|
81
|
+
otlp_logs_export_enabled: otlp_logs_export_enabled,
|
|
79
82
|
}
|
|
80
83
|
end
|
|
81
84
|
|
|
@@ -159,8 +162,40 @@ module Datadog
|
|
|
159
162
|
!!Datadog.configuration.health_metrics.enabled
|
|
160
163
|
end
|
|
161
164
|
|
|
165
|
+
# @return [Boolean] whether the tracer exports traces over OTLP.
|
|
166
|
+
# Always false: Ruby exports spans in Datadog's native format and has no OTLP trace exporter.
|
|
167
|
+
def otlp_traces_export_enabled
|
|
168
|
+
false
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# @return [Boolean] whether the tracer exports metrics over OTLP
|
|
172
|
+
def otlp_metrics_export_enabled
|
|
173
|
+
metrics = opentelemetry_settings&.metrics
|
|
174
|
+
# A "none" exporter skips the OTLP metric reader even when metrics are enabled
|
|
175
|
+
# (mirrors Datadog::OpenTelemetry::Ext::EXPORTER_NONE).
|
|
176
|
+
!!(metrics&.enabled && metrics.exporter != "none")
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# @return [Boolean] whether the tracer exports logs over OTLP
|
|
180
|
+
def otlp_logs_export_enabled
|
|
181
|
+
logs = opentelemetry_settings&.logs
|
|
182
|
+
# A "none" exporter skips the OTLP log record processor even when logs are enabled
|
|
183
|
+
# (mirrors Datadog::OpenTelemetry::Ext::EXPORTER_NONE).
|
|
184
|
+
!!(logs&.enabled && logs.exporter != "none")
|
|
185
|
+
end
|
|
186
|
+
|
|
162
187
|
private
|
|
163
188
|
|
|
189
|
+
# The `opentelemetry` settings namespace is registered by core configuration, but access it
|
|
190
|
+
# defensively so a missing/unregistered namespace defaults to `false` rather than raising.
|
|
191
|
+
def opentelemetry_settings
|
|
192
|
+
return unless Datadog.configuration.respond_to?(:opentelemetry)
|
|
193
|
+
|
|
194
|
+
Datadog.configuration.opentelemetry
|
|
195
|
+
rescue
|
|
196
|
+
nil
|
|
197
|
+
end
|
|
198
|
+
|
|
164
199
|
# Outputs "k1:v1,k2:v2,..."
|
|
165
200
|
def hash_serializer(h)
|
|
166
201
|
h.map { |k, v| "#{k}:#{v}" }.join(",")
|
|
@@ -16,8 +16,8 @@ module Datadog
|
|
|
16
16
|
"#{Ext::TAG_LANG_VERSION}:#{Environment::Identity.lang_version}",
|
|
17
17
|
# TODO: Technically not accurate, if tracing version diverges from datadog gem version
|
|
18
18
|
# If we extract tracing to its own gem, this needs to be updated.
|
|
19
|
-
"#{Ext::TAG_TRACER_VERSION}:#{Environment::Identity.gem_datadog_version}"
|
|
20
|
-
].freeze
|
|
19
|
+
"#{Ext::TAG_TRACER_VERSION}:#{Environment::Identity.gem_datadog_version}",
|
|
20
|
+
].freeze,
|
|
21
21
|
}.freeze
|
|
22
22
|
|
|
23
23
|
def metric_options(options = nil)
|
|
@@ -53,7 +53,7 @@ module Datadog
|
|
|
53
53
|
service_version: settings.version || "",
|
|
54
54
|
# Follows Java: https://github.com/DataDog/dd-trace-java/blob/2ebc964340ac530342cc389ba68ff0f5070d5f9f/dd-trace-core/src/main/java/datadog/trace/core/servicediscovery/ServiceDiscovery.java#L37-L38
|
|
55
55
|
process_tags: settings.experimental_propagate_process_tags_enabled ? Core::Environment::Process.serialized : "",
|
|
56
|
-
container_id: Core::Environment::Container.container_id || ""
|
|
56
|
+
container_id: Core::Environment::Container.container_id || "",
|
|
57
57
|
}
|
|
58
58
|
end
|
|
59
59
|
end
|
|
@@ -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
|