datadog 2.23.0 → 2.25.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 +67 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +17 -5
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +4 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/lib/datadog/ai_guard/api_client.rb +82 -0
- data/lib/datadog/ai_guard/component.rb +42 -0
- data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
- data/lib/datadog/ai_guard/configuration/settings.rb +98 -0
- data/lib/datadog/ai_guard/configuration.rb +11 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +34 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +81 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +43 -0
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
- data/lib/datadog/ai_guard/evaluation.rb +72 -0
- data/lib/datadog/ai_guard/ext.rb +16 -0
- data/lib/datadog/ai_guard.rb +153 -0
- data/lib/datadog/appsec/context.rb +2 -1
- data/lib/datadog/appsec/remote.rb +5 -12
- data/lib/datadog/appsec/security_engine/engine.rb +3 -3
- data/lib/datadog/appsec/security_engine/result.rb +2 -1
- data/lib/datadog/appsec/security_engine/runner.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +6 -0
- data/lib/datadog/core/configuration/config_helper.rb +1 -1
- data/lib/datadog/core/configuration/deprecations.rb +2 -2
- data/lib/datadog/core/configuration/option_definition.rb +4 -2
- data/lib/datadog/core/configuration/options.rb +8 -5
- data/lib/datadog/core/configuration/settings.rb +14 -3
- data/lib/datadog/core/configuration/supported_configurations.rb +8 -1
- data/lib/datadog/core/environment/cgroup.rb +52 -25
- data/lib/datadog/core/environment/container.rb +140 -46
- data/lib/datadog/core/environment/ext.rb +1 -0
- data/lib/datadog/core/environment/process.rb +9 -1
- data/lib/datadog/core/error.rb +6 -6
- data/lib/datadog/core/pin.rb +4 -0
- data/lib/datadog/core/rate_limiter.rb +9 -1
- data/lib/datadog/core/remote/client.rb +14 -6
- data/lib/datadog/core/remote/component.rb +6 -4
- data/lib/datadog/core/remote/configuration/content.rb +15 -2
- data/lib/datadog/core/remote/configuration/digest.rb +14 -7
- data/lib/datadog/core/remote/configuration/repository.rb +1 -1
- data/lib/datadog/core/remote/configuration/target.rb +13 -6
- data/lib/datadog/core/remote/transport/config.rb +3 -16
- data/lib/datadog/core/remote/transport/http/config.rb +4 -44
- data/lib/datadog/core/remote/transport/http/negotiation.rb +0 -39
- data/lib/datadog/core/remote/transport/http.rb +13 -24
- data/lib/datadog/core/remote/transport/negotiation.rb +7 -16
- data/lib/datadog/core/semaphore.rb +1 -4
- data/lib/datadog/core/telemetry/component.rb +52 -13
- data/lib/datadog/core/telemetry/event/app_started.rb +36 -1
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
- data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
- data/lib/datadog/core/telemetry/request.rb +17 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -32
- data/lib/datadog/core/telemetry/transport/http.rb +21 -16
- data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -10
- data/lib/datadog/core/telemetry/worker.rb +88 -32
- data/lib/datadog/core/transport/ext.rb +2 -0
- data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
- data/lib/datadog/core/transport/http/api/instance.rb +4 -21
- data/lib/datadog/core/transport/http/builder.rb +9 -5
- data/lib/datadog/core/transport/http/client.rb +19 -8
- data/lib/datadog/core/transport/http.rb +22 -19
- data/lib/datadog/core/transport/response.rb +12 -1
- data/lib/datadog/core/transport/transport.rb +90 -0
- data/lib/datadog/core/utils/only_once_successful.rb +2 -0
- data/lib/datadog/core/utils/safe_dup.rb +2 -2
- data/lib/datadog/core/utils/sequence.rb +2 -0
- data/lib/datadog/core/utils/time.rb +1 -1
- data/lib/datadog/core/workers/async.rb +10 -1
- data/lib/datadog/core/workers/interval_loop.rb +44 -3
- data/lib/datadog/core/workers/polling.rb +2 -0
- data/lib/datadog/core/workers/queue.rb +100 -1
- data/lib/datadog/data_streams/processor.rb +1 -1
- data/lib/datadog/data_streams/transport/http/stats.rb +1 -36
- data/lib/datadog/data_streams/transport/http.rb +5 -6
- data/lib/datadog/data_streams/transport/stats.rb +3 -17
- data/lib/datadog/di/boot.rb +4 -2
- data/lib/datadog/di/contrib/active_record.rb +30 -5
- data/lib/datadog/di/el/compiler.rb +8 -4
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +26 -7
- data/lib/datadog/di/logger.rb +2 -2
- data/lib/datadog/di/probe_builder.rb +2 -1
- data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
- data/lib/datadog/di/probe_manager.rb +37 -31
- data/lib/datadog/di/probe_notification_builder.rb +15 -2
- data/lib/datadog/di/probe_notifier_worker.rb +5 -5
- data/lib/datadog/di/remote.rb +89 -84
- data/lib/datadog/di/transport/diagnostics.rb +7 -35
- data/lib/datadog/di/transport/http/diagnostics.rb +1 -31
- data/lib/datadog/di/transport/http/input.rb +1 -31
- data/lib/datadog/di/transport/http.rb +28 -17
- data/lib/datadog/di/transport/input.rb +7 -34
- data/lib/datadog/di.rb +61 -5
- data/lib/datadog/error_tracking/filters.rb +2 -2
- data/lib/datadog/kit/appsec/events/v2.rb +2 -3
- data/lib/datadog/open_feature/evaluation_engine.rb +2 -1
- data/lib/datadog/open_feature/remote.rb +3 -10
- data/lib/datadog/open_feature/transport.rb +9 -11
- data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +2 -2
- data/lib/datadog/opentelemetry/metrics.rb +21 -14
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +5 -8
- data/lib/datadog/profiling/collectors/code_provenance.rb +27 -2
- data/lib/datadog/profiling/collectors/info.rb +5 -4
- data/lib/datadog/profiling/component.rb +12 -11
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
- data/lib/datadog/profiling/http_transport.rb +4 -1
- data/lib/datadog/tracing/contrib/extensions.rb +10 -2
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +31 -32
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +2 -1
- data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +6 -3
- data/lib/datadog/tracing/contrib/waterdrop.rb +4 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -2
- data/lib/datadog/tracing/remote.rb +1 -9
- data/lib/datadog/tracing/sampling/priority_sampler.rb +3 -1
- data/lib/datadog/tracing/span.rb +1 -1
- data/lib/datadog/tracing/span_event.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +20 -9
- data/lib/datadog/tracing/trace_operation.rb +44 -6
- data/lib/datadog/tracing/tracer.rb +42 -16
- data/lib/datadog/tracing/transport/http/traces.rb +2 -50
- data/lib/datadog/tracing/transport/http.rb +15 -9
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/transport/traces.rb +6 -66
- data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
- data/lib/datadog/tracing/writer.rb +1 -0
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +1 -0
- metadata +24 -17
- data/lib/datadog/core/remote/transport/http/api.rb +0 -53
- data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
- data/lib/datadog/core/transport/http/api/spec.rb +0 -36
- data/lib/datadog/data_streams/transport/http/api.rb +0 -33
- data/lib/datadog/data_streams/transport/http/client.rb +0 -21
- data/lib/datadog/di/transport/http/api.rb +0 -42
- data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
- data/lib/datadog/tracing/transport/http/api.rb +0 -44
|
@@ -11,9 +11,11 @@ module Datadog
|
|
|
11
11
|
module Core
|
|
12
12
|
module Remote
|
|
13
13
|
# Configures the HTTP transport to communicate with the agent
|
|
14
|
-
# to fetch and sync the remote configuration
|
|
14
|
+
# to fetch and sync the remote configuration.
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
15
17
|
class Component
|
|
16
|
-
attr_reader :logger, :client, :healthy
|
|
18
|
+
attr_reader :logger, :client, :healthy, :worker
|
|
17
19
|
|
|
18
20
|
def initialize(settings, capabilities, agent_settings, logger:)
|
|
19
21
|
@logger = logger
|
|
@@ -23,7 +25,7 @@ module Datadog
|
|
|
23
25
|
|
|
24
26
|
@barrier = Barrier.new(settings.remote.boot_timeout_seconds)
|
|
25
27
|
|
|
26
|
-
@client = Client.new(transport_v7, capabilities, logger: logger)
|
|
28
|
+
@client = Client.new(transport_v7, capabilities, settings: settings, logger: logger)
|
|
27
29
|
@healthy = false
|
|
28
30
|
logger.debug { "new remote configuration client: #{@client.id}" }
|
|
29
31
|
|
|
@@ -55,7 +57,7 @@ module Datadog
|
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
# client state is unknown, state might be corrupted
|
|
58
|
-
@client = Client.new(transport_v7, capabilities, logger: logger)
|
|
60
|
+
@client = Client.new(transport_v7, capabilities, settings: settings, logger: logger)
|
|
59
61
|
@healthy = false
|
|
60
62
|
logger.debug { "new remote configuration client: #{@client.id}" }
|
|
61
63
|
|
|
@@ -22,6 +22,18 @@ module Datadog
|
|
|
22
22
|
attr_accessor :version
|
|
23
23
|
|
|
24
24
|
def initialize(path:, data:)
|
|
25
|
+
if data.nil?
|
|
26
|
+
# +data+ is passed to Digest calculation and also is
|
|
27
|
+
# unconditionally taken length of by +length+ method.
|
|
28
|
+
# As such, the class is not written to expect +data+ to be nil.
|
|
29
|
+
# Detect bad incoming values here to provide earlier diagnostics
|
|
30
|
+
# when developing tests, for example.
|
|
31
|
+
raise ArgumentError, 'data must not be nil'
|
|
32
|
+
end
|
|
33
|
+
unless String === data
|
|
34
|
+
raise ArgumentError, "Invalid type for data: #{data.class}: expected String"
|
|
35
|
+
end
|
|
36
|
+
|
|
25
37
|
@path = path
|
|
26
38
|
@data = data
|
|
27
39
|
@apply_state = ApplyState::UNACKNOWLEDGED
|
|
@@ -72,8 +84,9 @@ module Datadog
|
|
|
72
84
|
private_class_method :new
|
|
73
85
|
end
|
|
74
86
|
|
|
75
|
-
# ContentList stores a list of
|
|
76
|
-
# It provides
|
|
87
|
+
# ContentList stores a list of Content instances.
|
|
88
|
+
# It provides convenient methods for finding content based on
|
|
89
|
+
# Configuration::Path and Configuration::Target.
|
|
77
90
|
class ContentList < Array
|
|
78
91
|
class << self
|
|
79
92
|
def parse(array)
|
|
@@ -24,10 +24,21 @@ module Datadog
|
|
|
24
24
|
class InvalidHashTypeError < StandardError; end
|
|
25
25
|
attr_reader :type, :hexdigest
|
|
26
26
|
|
|
27
|
-
DIGEST_CHUNK = 1024
|
|
28
|
-
|
|
29
27
|
class << self
|
|
30
28
|
def hexdigest(type, data)
|
|
29
|
+
unless String === data
|
|
30
|
+
# This class (Digest) passes +data+ to the Ruby standard
|
|
31
|
+
# library Digest routines without validating its type.
|
|
32
|
+
# The stdlib Digest requires a String, and the previous
|
|
33
|
+
# implementation of this class that used StringIO
|
|
34
|
+
# unconditionally read from +data+ without validating the
|
|
35
|
+
# type. Meaning, passing +nil+ as +data+ has never worked.
|
|
36
|
+
# It still doesn't work in the present implementation.
|
|
37
|
+
# Flag the nil data now to get earlier diagnostics when
|
|
38
|
+
# developing tests for example.
|
|
39
|
+
raise ArgumentError, "Invalid type for data: #{data.class}: expected String"
|
|
40
|
+
end
|
|
41
|
+
|
|
31
42
|
d = case type
|
|
32
43
|
when :sha256
|
|
33
44
|
::Digest::SHA256.new
|
|
@@ -37,13 +48,9 @@ module Datadog
|
|
|
37
48
|
raise InvalidHashTypeError, type
|
|
38
49
|
end
|
|
39
50
|
|
|
40
|
-
|
|
41
|
-
d.update(buf)
|
|
42
|
-
end
|
|
51
|
+
d.update(data)
|
|
43
52
|
|
|
44
53
|
d.hexdigest
|
|
45
|
-
ensure
|
|
46
|
-
data.rewind
|
|
47
54
|
end
|
|
48
55
|
end
|
|
49
56
|
|
|
@@ -11,8 +11,15 @@ module Datadog
|
|
|
11
11
|
class TargetMap < Hash
|
|
12
12
|
class << self
|
|
13
13
|
def parse(hash)
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
signed = hash.fetch('signed')
|
|
15
|
+
# Note that the +dig+ call permits +hash['signed']+ to be
|
|
16
|
+
# missing the +custom+ subtree entirely.
|
|
17
|
+
# Previously the subtree was required but +opaque_backend_state+
|
|
18
|
+
# could still be missing (and obtained here as nil).
|
|
19
|
+
opaque_backend_state = signed.dig('custom', 'opaque_backend_state')
|
|
20
|
+
# The version appears to be optional to the rest of this class,
|
|
21
|
+
# and we have tests that do not provide it.
|
|
22
|
+
version = signed['version']
|
|
16
23
|
|
|
17
24
|
map = new
|
|
18
25
|
|
|
@@ -21,7 +28,7 @@ module Datadog
|
|
|
21
28
|
@version = version
|
|
22
29
|
end
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
signed.fetch('targets').each_with_object(map) do |(p, t), m|
|
|
25
32
|
path = Configuration::Path.parse(p)
|
|
26
33
|
target = Configuration::Target.parse(t)
|
|
27
34
|
|
|
@@ -46,9 +53,9 @@ module Datadog
|
|
|
46
53
|
class Target
|
|
47
54
|
class << self
|
|
48
55
|
def parse(hash)
|
|
49
|
-
length = Integer(hash
|
|
50
|
-
digests = Configuration::DigestList.parse(hash
|
|
51
|
-
version = Integer(hash
|
|
56
|
+
length = Integer(hash.fetch('length'))
|
|
57
|
+
digests = Configuration::DigestList.parse(hash.fetch('hashes'))
|
|
58
|
+
version = Integer(hash.dig('custom', 'v'))
|
|
52
59
|
|
|
53
60
|
new(digests: digests, length: length, version: version)
|
|
54
61
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative '../../../core/transport/request'
|
|
4
4
|
require_relative '../../../core/transport/parcel'
|
|
5
|
+
require_relative '../../../core/transport/transport'
|
|
5
6
|
require_relative 'http/config'
|
|
6
7
|
|
|
7
8
|
module Datadog
|
|
@@ -23,27 +24,13 @@ module Datadog
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
# Config transport
|
|
26
|
-
class Transport
|
|
27
|
-
attr_reader :client, :apis, :default_api, :current_api_id, :logger
|
|
28
|
-
|
|
29
|
-
def initialize(apis, default_api, logger: Datadog.logger)
|
|
30
|
-
@apis = apis
|
|
31
|
-
@logger = logger
|
|
32
|
-
|
|
33
|
-
@client = Remote::Transport::HTTP::Config::Client.new(current_api, logger: logger)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
##### there is only one transport! it's negotiation!
|
|
27
|
+
class Transport < Core::Transport::Transport
|
|
37
28
|
def send_config(payload)
|
|
38
29
|
json = JSON.dump(payload)
|
|
39
30
|
parcel = EncodedParcel.new(json)
|
|
40
31
|
request = Request.new(parcel)
|
|
41
32
|
|
|
42
|
-
@client.
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def current_api
|
|
46
|
-
@apis[HTTP::API::V7]
|
|
33
|
+
@client.send_request(:config, request)
|
|
47
34
|
end
|
|
48
35
|
end
|
|
49
36
|
end
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
4
|
|
|
5
|
-
require_relative '../../../transport/http/
|
|
5
|
+
require_relative '../../../transport/http/api/endpoint'
|
|
6
|
+
require_relative '../../../transport/http/response'
|
|
6
7
|
require_relative '../../../utils/base64'
|
|
7
8
|
require_relative '../../../utils/truncation'
|
|
8
|
-
require_relative '../../../transport/http/response'
|
|
9
|
-
require_relative '../../../transport/http/api/endpoint'
|
|
10
9
|
|
|
11
10
|
module Datadog
|
|
12
11
|
module Core
|
|
@@ -17,7 +16,7 @@ module Datadog
|
|
|
17
16
|
module Config
|
|
18
17
|
# Response from HTTP transport for remote configuration
|
|
19
18
|
class Response
|
|
20
|
-
include
|
|
19
|
+
include Core::Transport::HTTP::Response
|
|
21
20
|
|
|
22
21
|
def initialize(http_response, options = {}) # standard:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
23
22
|
super(http_response)
|
|
@@ -101,7 +100,7 @@ module Datadog
|
|
|
101
100
|
|
|
102
101
|
{
|
|
103
102
|
path: h[:path].freeze,
|
|
104
|
-
content:
|
|
103
|
+
content: content.freeze,
|
|
105
104
|
}
|
|
106
105
|
end.freeze
|
|
107
106
|
|
|
@@ -178,46 +177,7 @@ module Datadog
|
|
|
178
177
|
end
|
|
179
178
|
end
|
|
180
179
|
|
|
181
|
-
# Remote transport HTTP client
|
|
182
|
-
class Client < Core::Transport::HTTP::Client
|
|
183
|
-
def send_config_payload(request)
|
|
184
|
-
send_request(request) do |api, env|
|
|
185
|
-
api.send_config(env)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
180
|
module API
|
|
191
|
-
# Extensions for HTTP API Spec
|
|
192
|
-
module Spec
|
|
193
|
-
attr_reader :config
|
|
194
|
-
|
|
195
|
-
def config=(endpoint)
|
|
196
|
-
@config = endpoint
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def send_config(env, &block)
|
|
200
|
-
raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('config', self) if config.nil?
|
|
201
|
-
|
|
202
|
-
config.call(env, &block)
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
# Extensions for HTTP API Instance
|
|
207
|
-
module Instance
|
|
208
|
-
def send_config(env)
|
|
209
|
-
unless spec.is_a?(Config::API::Spec)
|
|
210
|
-
raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new(
|
|
211
|
-
'config', self
|
|
212
|
-
)
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
spec.send_config(env) do |request_env|
|
|
216
|
-
call(request_env)
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
181
|
# Endpoint for remote configuration
|
|
222
182
|
class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
|
|
223
183
|
HEADER_CONTENT_TYPE = 'Content-Type'
|
|
@@ -43,46 +43,7 @@ module Datadog
|
|
|
43
43
|
attr_reader :version, :endpoints, :config, :span_events
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
# Remote negotiation HTTP client
|
|
47
|
-
class Client < Core::Transport::HTTP::Client
|
|
48
|
-
def send_info_payload(request)
|
|
49
|
-
send_request(request) do |api, env|
|
|
50
|
-
api.send_info(env)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
46
|
module API
|
|
56
|
-
# Extensions for HTTP API Spec
|
|
57
|
-
module Spec
|
|
58
|
-
attr_reader :info
|
|
59
|
-
|
|
60
|
-
def info=(endpoint)
|
|
61
|
-
@info = endpoint
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def send_info(env, &block)
|
|
65
|
-
raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('info', self) if info.nil?
|
|
66
|
-
|
|
67
|
-
info.call(env, &block)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Extensions for HTTP API Instance
|
|
72
|
-
module Instance
|
|
73
|
-
def send_info(env)
|
|
74
|
-
unless spec.is_a?(Negotiation::API::Spec)
|
|
75
|
-
raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new(
|
|
76
|
-
'info', self
|
|
77
|
-
)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
spec.send_info(env) do |request_env|
|
|
81
|
-
call(request_env)
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
47
|
# Endpoint for negotiation
|
|
87
48
|
class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
|
|
88
49
|
def initialize(path)
|
|
@@ -7,16 +7,6 @@ require_relative '../../transport/http'
|
|
|
7
7
|
require_relative 'config'
|
|
8
8
|
require_relative 'negotiation'
|
|
9
9
|
|
|
10
|
-
# TODO: Improve negotiation to allow per endpoint selection
|
|
11
|
-
#
|
|
12
|
-
# Since endpoint negotiation happens at the `API::Spec` level there can not be
|
|
13
|
-
# a mix of endpoints at various versions or versionless without describing all
|
|
14
|
-
# the possible combinations as specs. See http/api.
|
|
15
|
-
#
|
|
16
|
-
# Below should be:
|
|
17
|
-
# require_relative '../../transport/http/api'
|
|
18
|
-
require_relative 'http/api'
|
|
19
|
-
|
|
20
10
|
# TODO: Decouple transport/http
|
|
21
11
|
#
|
|
22
12
|
# Because a new transport is required for every (API, Client, Transport)
|
|
@@ -29,26 +19,30 @@ module Datadog
|
|
|
29
19
|
module Transport
|
|
30
20
|
# Namespace for HTTP transport components
|
|
31
21
|
module HTTP
|
|
22
|
+
ROOT = Negotiation::API::Endpoint.new(
|
|
23
|
+
'/info',
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
V7 = Config::API::Endpoint.new(
|
|
27
|
+
'/v0.7/config',
|
|
28
|
+
Core::Encoding::JSONEncoder,
|
|
29
|
+
)
|
|
30
|
+
|
|
32
31
|
module_function
|
|
33
32
|
|
|
34
33
|
# Builds a new Transport::HTTP::Client with default settings
|
|
35
34
|
# Pass a block to override any settings.
|
|
36
35
|
def root(
|
|
37
36
|
agent_settings:,
|
|
38
|
-
logger
|
|
39
|
-
api_version: nil,
|
|
37
|
+
logger:,
|
|
40
38
|
headers: nil
|
|
41
39
|
)
|
|
42
40
|
Core::Transport::HTTP.build(
|
|
43
|
-
api_instance_class: API::Instance,
|
|
44
41
|
agent_settings: agent_settings,
|
|
45
42
|
logger: logger,
|
|
46
|
-
api_version: api_version,
|
|
47
43
|
headers: headers
|
|
48
44
|
) do |transport|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
transport.api API::ROOT, apis[API::ROOT]
|
|
45
|
+
transport.api 'root', ROOT
|
|
52
46
|
|
|
53
47
|
# Call block to apply any customization, if provided
|
|
54
48
|
yield(transport) if block_given?
|
|
@@ -59,20 +53,15 @@ module Datadog
|
|
|
59
53
|
# Pass a block to override any settings.
|
|
60
54
|
def v7(
|
|
61
55
|
agent_settings:,
|
|
62
|
-
logger
|
|
63
|
-
api_version: nil,
|
|
56
|
+
logger:,
|
|
64
57
|
headers: nil
|
|
65
58
|
)
|
|
66
59
|
Core::Transport::HTTP.build(
|
|
67
|
-
api_instance_class: API::Instance,
|
|
68
60
|
agent_settings: agent_settings,
|
|
69
61
|
logger: logger,
|
|
70
|
-
api_version: api_version,
|
|
71
62
|
headers: headers
|
|
72
63
|
) do |transport|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
transport.api API::V7, apis[API::V7]
|
|
64
|
+
transport.api 'v7', V7
|
|
76
65
|
|
|
77
66
|
# Call block to apply any customization, if provided
|
|
78
67
|
yield(transport) if block_given?
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../../../core/transport/request'
|
|
4
|
+
require_relative '../../../core/transport/transport'
|
|
4
5
|
require_relative 'http/negotiation'
|
|
5
6
|
|
|
6
7
|
# TODO: Resolve conceptual conundrum
|
|
@@ -32,24 +33,14 @@ module Datadog
|
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
# Negotiation transport
|
|
35
|
-
class Transport
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@logger = logger
|
|
41
|
-
|
|
42
|
-
@client = Remote::Transport::HTTP::Negotiation::Client.new(current_api, logger: logger)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def send_info
|
|
36
|
+
class Transport < Core::Transport::Transport
|
|
37
|
+
# TODO steep is complaining about this method, I tried to make
|
|
38
|
+
# it work but between module inclusions and steep diagnostics
|
|
39
|
+
# I don't understand what the problem is or what the steep wants.
|
|
40
|
+
def send_info # steep:ignore
|
|
46
41
|
request = Request.new
|
|
47
42
|
|
|
48
|
-
@client.
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def current_api
|
|
52
|
-
@apis[HTTP::API::ROOT]
|
|
43
|
+
@client.send_request(:info, request)
|
|
53
44
|
end
|
|
54
45
|
end
|
|
55
46
|
end
|
|
@@ -20,10 +20,7 @@ module Datadog
|
|
|
20
20
|
|
|
21
21
|
def wait(timeout = nil)
|
|
22
22
|
wake_lock.synchronize do
|
|
23
|
-
|
|
24
|
-
# ::Time::_Timeout which for some reason is not Numeric and is not
|
|
25
|
-
# castable from Numeric.
|
|
26
|
-
wake.wait(wake_lock, timeout) # steep:ignore
|
|
23
|
+
wake.wait(wake_lock, timeout)
|
|
27
24
|
end
|
|
28
25
|
end
|
|
29
26
|
|
|
@@ -14,14 +14,26 @@ require_relative '../utils/forking'
|
|
|
14
14
|
module Datadog
|
|
15
15
|
module Core
|
|
16
16
|
module Telemetry
|
|
17
|
-
# Telemetry
|
|
18
|
-
#
|
|
17
|
+
# Telemetry entry point, coordinates sending telemetry events at
|
|
18
|
+
# various points in application lifecycle.
|
|
19
19
|
#
|
|
20
20
|
# @api private
|
|
21
21
|
class Component
|
|
22
22
|
ENDPOINT_COLLECTION_MESSAGE_LIMIT = 300
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
ONLY_ONCE = Utils::OnlyOnce.new
|
|
25
|
+
|
|
26
|
+
attr_reader :enabled
|
|
27
|
+
attr_reader :logger
|
|
28
|
+
attr_reader :transport
|
|
29
|
+
attr_reader :worker
|
|
30
|
+
attr_reader :settings
|
|
31
|
+
attr_reader :agent_settings
|
|
32
|
+
attr_reader :metrics_manager
|
|
33
|
+
|
|
34
|
+
# Alias for consistency with other components.
|
|
35
|
+
# TODO Remove +enabled+ method
|
|
36
|
+
alias_method :enabled?, :enabled
|
|
25
37
|
|
|
26
38
|
include Core::Utils::Forking
|
|
27
39
|
include Telemetry::Logging
|
|
@@ -50,6 +62,17 @@ module Datadog
|
|
|
50
62
|
logger:,
|
|
51
63
|
enabled:
|
|
52
64
|
)
|
|
65
|
+
ONLY_ONCE.run do
|
|
66
|
+
Utils::AtForkMonkeyPatch.apply!
|
|
67
|
+
|
|
68
|
+
# All of the other at fork monkey patch callbacks reference
|
|
69
|
+
# globals, follow that pattern here to avoid having the component
|
|
70
|
+
# referenced via the at fork callbacks.
|
|
71
|
+
Datadog::Core::Utils::AtForkMonkeyPatch.at_fork(:child) do
|
|
72
|
+
Datadog.send(:components, allow_initialization: false)&.telemetry&.after_fork
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
53
76
|
@enabled = enabled
|
|
54
77
|
@log_collection_enabled = settings.telemetry.log_collection_enabled
|
|
55
78
|
@logger = logger
|
|
@@ -110,7 +133,7 @@ module Datadog
|
|
|
110
133
|
end
|
|
111
134
|
|
|
112
135
|
def start(initial_event_is_change = false, components:)
|
|
113
|
-
return
|
|
136
|
+
return unless enabled?
|
|
114
137
|
|
|
115
138
|
initial_event = if initial_event_is_change
|
|
116
139
|
Event::SynthAppClientConfigurationChange.new(
|
|
@@ -136,44 +159,44 @@ module Datadog
|
|
|
136
159
|
end
|
|
137
160
|
|
|
138
161
|
def emit_closing!
|
|
139
|
-
return
|
|
162
|
+
return unless enabled?
|
|
140
163
|
|
|
141
164
|
@worker.enqueue(Event::AppClosing.new)
|
|
142
165
|
end
|
|
143
166
|
|
|
144
167
|
def integrations_change!
|
|
145
|
-
return
|
|
168
|
+
return unless enabled?
|
|
146
169
|
|
|
147
170
|
@worker.enqueue(Event::AppIntegrationsChange.new)
|
|
148
171
|
end
|
|
149
172
|
|
|
150
173
|
def log!(event)
|
|
151
|
-
return
|
|
174
|
+
return unless enabled? && @log_collection_enabled
|
|
152
175
|
|
|
153
176
|
@worker.enqueue(event)
|
|
154
177
|
end
|
|
155
178
|
|
|
156
179
|
# Wait for the worker to send out all events that have already
|
|
157
180
|
# been queued, up to 15 seconds. Returns whether all events have
|
|
158
|
-
# been flushed.
|
|
181
|
+
# been flushed, or nil if telemetry is disabled.
|
|
159
182
|
#
|
|
160
183
|
# @api private
|
|
161
|
-
def flush
|
|
162
|
-
return
|
|
184
|
+
def flush(timeout: nil)
|
|
185
|
+
return unless enabled?
|
|
163
186
|
|
|
164
|
-
@worker.flush
|
|
187
|
+
@worker.flush(timeout: timeout)
|
|
165
188
|
end
|
|
166
189
|
|
|
167
190
|
# Report configuration changes caused by Remote Configuration.
|
|
168
191
|
def client_configuration_change!(changes)
|
|
169
|
-
return
|
|
192
|
+
return unless enabled?
|
|
170
193
|
|
|
171
194
|
@worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
|
|
172
195
|
end
|
|
173
196
|
|
|
174
197
|
# Report application endpoints
|
|
175
198
|
def app_endpoints_loaded(endpoints, page_size: ENDPOINT_COLLECTION_MESSAGE_LIMIT)
|
|
176
|
-
return
|
|
199
|
+
return unless enabled?
|
|
177
200
|
|
|
178
201
|
endpoints.each_slice(page_size).with_index do |endpoints_slice, i|
|
|
179
202
|
@worker.enqueue(Event::AppEndpointsLoaded.new(endpoints_slice, is_first: i.zero?))
|
|
@@ -204,6 +227,22 @@ module Datadog
|
|
|
204
227
|
def distribution(namespace, metric_name, value, tags: {}, common: true)
|
|
205
228
|
@metrics_manager.distribution(namespace, metric_name, value, tags: tags, common: common)
|
|
206
229
|
end
|
|
230
|
+
|
|
231
|
+
# When a fork happens, we generally need to do two things inside the
|
|
232
|
+
# child proess:
|
|
233
|
+
# 1. Restart the worker.
|
|
234
|
+
# 2. Discard any events and metrics that were submitted in the
|
|
235
|
+
# parent process (because they will be sent out in the parent
|
|
236
|
+
# process, sending them in the child would cause duplicate
|
|
237
|
+
# submission).
|
|
238
|
+
def after_fork
|
|
239
|
+
# We cannot simply create a new instance of metrics manager because
|
|
240
|
+
# it is referenced from other objects (e.g. the worker).
|
|
241
|
+
# We must reset the existing instance.
|
|
242
|
+
@metrics_manager.clear
|
|
243
|
+
|
|
244
|
+
worker&.send(:after_fork_monkey_patched)
|
|
245
|
+
end
|
|
207
246
|
end
|
|
208
247
|
end
|
|
209
248
|
end
|
|
@@ -11,6 +11,12 @@ module Datadog
|
|
|
11
11
|
def initialize(components:)
|
|
12
12
|
# To not hold a reference to the component tree, generate
|
|
13
13
|
# the event payload here in the constructor.
|
|
14
|
+
#
|
|
15
|
+
# Important: do not store data that contains (or is derived from)
|
|
16
|
+
# the runtime_id or sequence numbers.
|
|
17
|
+
# This event is reused when a process forks, but in the
|
|
18
|
+
# child process the runtime_id would be different and sequence
|
|
19
|
+
# number is reset.
|
|
14
20
|
@configuration = configuration(components.settings, components.agent_settings)
|
|
15
21
|
@install_signature = install_signature(components.settings)
|
|
16
22
|
@products = products(components)
|
|
@@ -30,10 +36,19 @@ module Datadog
|
|
|
30
36
|
}
|
|
31
37
|
end
|
|
32
38
|
|
|
39
|
+
# Whether the event is actually the app-started event.
|
|
40
|
+
# For the app-started event we follow up by sending
|
|
41
|
+
# app-dependencies-loaded, if the event is
|
|
42
|
+
# app-client-configuration-change we don't send
|
|
43
|
+
# app-dependencies-loaded.
|
|
44
|
+
def app_started?
|
|
45
|
+
true
|
|
46
|
+
end
|
|
47
|
+
|
|
33
48
|
private
|
|
34
49
|
|
|
35
50
|
def products(components)
|
|
36
|
-
# @type var products:
|
|
51
|
+
# @type var products: telemetry_products
|
|
37
52
|
products = {
|
|
38
53
|
appsec: {
|
|
39
54
|
# TODO take appsec status out of component tree?
|
|
@@ -159,6 +174,25 @@ module Datadog
|
|
|
159
174
|
get_telemetry_origin(settings, 'tracing.contrib.peer_service_mapping')
|
|
160
175
|
)
|
|
161
176
|
|
|
177
|
+
# OpenTelemetry configuration options (using environment variable names)
|
|
178
|
+
otel_exporter_headers_string = settings.opentelemetry.exporter.headers&.map { |key, value| "#{key}=#{value}" }&.join(',')
|
|
179
|
+
otel_exporter_metrics_headers_string = settings.opentelemetry.metrics.headers&.map { |key, value| "#{key}=#{value}" }&.join(',')
|
|
180
|
+
list.push(
|
|
181
|
+
conf_value('OTEL_EXPORTER_OTLP_ENDPOINT', settings.opentelemetry.exporter.endpoint, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.endpoint')),
|
|
182
|
+
conf_value('OTEL_EXPORTER_OTLP_HEADERS', otel_exporter_headers_string, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.headers')),
|
|
183
|
+
conf_value('OTEL_EXPORTER_OTLP_PROTOCOL', settings.opentelemetry.exporter.protocol, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.protocol')),
|
|
184
|
+
conf_value('OTEL_EXPORTER_OTLP_TIMEOUT', settings.opentelemetry.exporter.timeout_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.timeout_millis')),
|
|
185
|
+
conf_value('DD_METRICS_OTEL_ENABLED', settings.opentelemetry.metrics.enabled, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.enabled')),
|
|
186
|
+
conf_value('OTEL_METRICS_EXPORTER', settings.opentelemetry.metrics.exporter, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.exporter')),
|
|
187
|
+
conf_value('OTEL_EXPORTER_OTLP_METRICS_ENDPOINT', settings.opentelemetry.metrics.endpoint, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.endpoint')),
|
|
188
|
+
conf_value('OTEL_EXPORTER_OTLP_METRICS_HEADERS', otel_exporter_metrics_headers_string, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.headers')),
|
|
189
|
+
conf_value('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL', settings.opentelemetry.metrics.protocol, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.protocol')),
|
|
190
|
+
conf_value('OTEL_EXPORTER_OTLP_METRICS_TIMEOUT', settings.opentelemetry.metrics.timeout_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.timeout_millis')),
|
|
191
|
+
conf_value('OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE', settings.opentelemetry.metrics.temporality_preference, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.temporality_preference')),
|
|
192
|
+
conf_value('OTEL_METRIC_EXPORT_INTERVAL', settings.opentelemetry.metrics.export_interval_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.export_interval_millis')),
|
|
193
|
+
conf_value('OTEL_METRIC_EXPORT_TIMEOUT', settings.opentelemetry.metrics.export_timeout_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.export_timeout_millis')),
|
|
194
|
+
)
|
|
195
|
+
|
|
162
196
|
# Whitelist of configuration options to send in additional payload object
|
|
163
197
|
TARGET_OPTIONS.each do |option_path|
|
|
164
198
|
split_option = option_path.split('.')
|
|
@@ -243,6 +277,7 @@ module Datadog
|
|
|
243
277
|
# - `default`: set when the user has not set any configuration for the key (defaults to a value)
|
|
244
278
|
# - `unknown`: set for cases where it is difficult/not possible to determine the source of a config.
|
|
245
279
|
def conf_value(name, value, seq_id, origin)
|
|
280
|
+
# @type var result: telemetry_configuration
|
|
246
281
|
result = {name: name, value: value, origin: origin, seq_id: seq_id}
|
|
247
282
|
if origin == 'fleet_stable_config'
|
|
248
283
|
fleet_id = Core::Configuration::StableConfig.configuration.dig(:fleet, :id)
|