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
|
@@ -1,43 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '../../../core/transport/http/api/
|
|
4
|
-
require_relative '../../../core/transport/http/api/spec'
|
|
5
|
-
require_relative '../../../core/transport/http/client'
|
|
3
|
+
require_relative '../../../core/transport/http/api/endpoint'
|
|
6
4
|
|
|
7
5
|
module Datadog
|
|
8
6
|
module DI
|
|
9
7
|
module Transport
|
|
10
8
|
module HTTP
|
|
11
9
|
module Diagnostics
|
|
12
|
-
class Client < Core::Transport::HTTP::Client
|
|
13
|
-
def send_diagnostics_payload(request)
|
|
14
|
-
send_request(request) do |api, env|
|
|
15
|
-
api.send_diagnostics(env)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
10
|
module API
|
|
21
|
-
class Instance < Core::Transport::HTTP::API::Instance
|
|
22
|
-
def send_diagnostics(env)
|
|
23
|
-
raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new('diagnostics', self) unless spec.is_a?(Diagnostics::API::Spec)
|
|
24
|
-
|
|
25
|
-
spec.send_diagnostics(env) do |request_env|
|
|
26
|
-
call(request_env)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
class Spec < Core::Transport::HTTP::API::Spec
|
|
32
|
-
attr_accessor :diagnostics
|
|
33
|
-
|
|
34
|
-
def send_diagnostics(env, &block)
|
|
35
|
-
raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('diagnostics', self) if diagnostics.nil?
|
|
36
|
-
|
|
37
|
-
diagnostics.call(env, &block)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
11
|
class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
|
|
42
12
|
attr_reader :encoder
|
|
43
13
|
|
|
@@ -1,43 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '../../../core/transport/http/api/
|
|
4
|
-
require_relative '../../../core/transport/http/api/spec'
|
|
5
|
-
require_relative '../../../core/transport/http/client'
|
|
3
|
+
require_relative '../../../core/transport/http/api/endpoint'
|
|
6
4
|
|
|
7
5
|
module Datadog
|
|
8
6
|
module DI
|
|
9
7
|
module Transport
|
|
10
8
|
module HTTP
|
|
11
9
|
module Input
|
|
12
|
-
class Client < Core::Transport::HTTP::Client
|
|
13
|
-
def send_input_payload(request)
|
|
14
|
-
send_request(request) do |api, env|
|
|
15
|
-
api.send_input(env)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
10
|
module API
|
|
21
|
-
class Instance < Core::Transport::HTTP::API::Instance
|
|
22
|
-
def send_input(env)
|
|
23
|
-
raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new('input', self) unless spec.is_a?(Input::API::Spec)
|
|
24
|
-
|
|
25
|
-
spec.send_input(env) do |request_env|
|
|
26
|
-
call(request_env)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
class Spec < Core::Transport::HTTP::API::Spec
|
|
32
|
-
attr_accessor :input
|
|
33
|
-
|
|
34
|
-
def send_input(env, &block)
|
|
35
|
-
raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('input', self) if input.nil?
|
|
36
|
-
|
|
37
|
-
input.call(env, &block)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
11
|
class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
|
|
42
12
|
HEADER_CONTENT_TYPE = 'Content-Type'
|
|
43
13
|
|
|
@@ -1,31 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../../core/encoding'
|
|
4
|
+
require_relative '../../core/transport/http'
|
|
3
5
|
require_relative 'diagnostics'
|
|
4
6
|
require_relative 'input'
|
|
5
|
-
require_relative 'http/api'
|
|
6
|
-
require_relative '../../core/transport/http'
|
|
7
7
|
|
|
8
8
|
module Datadog
|
|
9
9
|
module DI
|
|
10
10
|
module Transport
|
|
11
11
|
# Namespace for HTTP transport components
|
|
12
12
|
module HTTP
|
|
13
|
-
|
|
13
|
+
DIAGNOSTICS = Diagnostics::API::Endpoint.new(
|
|
14
|
+
'/debugger/v1/diagnostics',
|
|
15
|
+
Core::Encoding::JSONEncoder,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
INPUT = Input::API::Endpoint.new(
|
|
19
|
+
'/debugger/v2/input',
|
|
20
|
+
Core::Encoding::JSONEncoder,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
LEGACY_INPUT = Input::API::Endpoint.new(
|
|
24
|
+
# We used to use /debugger/v1/input, but now input
|
|
25
|
+
# payloads should be going to the diagnostics endpoint
|
|
26
|
+
# which I gather performs data redaction.
|
|
27
|
+
'/debugger/v1/diagnostics',
|
|
28
|
+
Core::Encoding::JSONEncoder,
|
|
29
|
+
)
|
|
14
30
|
|
|
15
31
|
# Builds a new Transport::HTTP::Client with default settings
|
|
16
32
|
# Pass a block to override any settings.
|
|
17
|
-
def diagnostics(
|
|
33
|
+
def self.diagnostics(
|
|
18
34
|
agent_settings:,
|
|
19
35
|
logger:,
|
|
20
|
-
api_version: nil,
|
|
21
36
|
headers: nil
|
|
22
37
|
)
|
|
23
|
-
Core::Transport::HTTP.build(
|
|
38
|
+
Core::Transport::HTTP.build(
|
|
24
39
|
logger: logger,
|
|
25
|
-
agent_settings: agent_settings,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
transport.api
|
|
40
|
+
agent_settings: agent_settings,
|
|
41
|
+
headers: headers,
|
|
42
|
+
) do |transport|
|
|
43
|
+
transport.api 'diagnostics', DIAGNOSTICS
|
|
29
44
|
|
|
30
45
|
# Call block to apply any customization, if provided
|
|
31
46
|
yield(transport) if block_given?
|
|
@@ -34,22 +49,18 @@ module Datadog
|
|
|
34
49
|
|
|
35
50
|
# Builds a new Transport::HTTP::Client with default settings
|
|
36
51
|
# Pass a block to override any settings.
|
|
37
|
-
def input(
|
|
52
|
+
def self.input(
|
|
38
53
|
agent_settings:,
|
|
39
54
|
logger:,
|
|
40
|
-
api_version: nil,
|
|
41
55
|
headers: nil
|
|
42
56
|
)
|
|
43
57
|
Core::Transport::HTTP.build(
|
|
44
|
-
api_instance_class: Input::API::Instance,
|
|
45
58
|
logger: logger,
|
|
46
59
|
agent_settings: agent_settings,
|
|
47
|
-
api_version: api_version,
|
|
48
60
|
headers: headers,
|
|
49
61
|
) do |transport|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
transport.api API::INPUT, apis[API::INPUT]
|
|
62
|
+
transport.api 'input', INPUT, fallback: 'legacy_input', default: true
|
|
63
|
+
transport.api 'legacy_input', LEGACY_INPUT
|
|
53
64
|
|
|
54
65
|
# Call block to apply any customization, if provided
|
|
55
66
|
yield(transport) if block_given?
|
|
@@ -5,6 +5,7 @@ require_relative '../../core/encoding'
|
|
|
5
5
|
require_relative '../../core/tag_builder'
|
|
6
6
|
require_relative '../../core/transport/parcel'
|
|
7
7
|
require_relative '../../core/transport/request'
|
|
8
|
+
require_relative '../../core/transport/transport'
|
|
8
9
|
require_relative '../error'
|
|
9
10
|
require_relative 'http/input'
|
|
10
11
|
|
|
@@ -26,9 +27,7 @@ module Datadog
|
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
|
|
29
|
-
class Transport
|
|
30
|
-
attr_reader :client, :apis, :default_api, :current_api_id, :logger
|
|
31
|
-
|
|
30
|
+
class Transport < Core::Transport::Transport
|
|
32
31
|
# The limit on an individual snapshot payload, aka "log line",
|
|
33
32
|
# is 1 MB.
|
|
34
33
|
#
|
|
@@ -48,17 +47,6 @@ module Datadog
|
|
|
48
47
|
# max chunk size, it will still get sent out.
|
|
49
48
|
DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024
|
|
50
49
|
|
|
51
|
-
def initialize(apis, default_api, logger:)
|
|
52
|
-
@apis = apis
|
|
53
|
-
@logger = logger
|
|
54
|
-
|
|
55
|
-
@client = DI::Transport::HTTP::Input::Client.new(current_api, logger: logger)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def current_api
|
|
59
|
-
@apis[HTTP::API::INPUT]
|
|
60
|
-
end
|
|
61
|
-
|
|
62
50
|
def send_input(payload, tags)
|
|
63
51
|
# Tags are the same for all chunks, serialize them one time.
|
|
64
52
|
serialized_tags = Core::TagBuilder.serialize_tags(tags)
|
|
@@ -101,27 +89,12 @@ module Datadog
|
|
|
101
89
|
parcel = EncodedParcel.new(chunked_payload)
|
|
102
90
|
request = Request.new(parcel, serialized_tags)
|
|
103
91
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
raise Error::AgentCommunicationError, "send_input failed: #{begin
|
|
110
|
-
response.code
|
|
111
|
-
rescue
|
|
112
|
-
"???"
|
|
113
|
-
end}: #{response.payload}"
|
|
92
|
+
client.send_request(:input, request).tap do |response|
|
|
93
|
+
if downgrade?(response)
|
|
94
|
+
downgrade!
|
|
95
|
+
return send_input_chunk(chunked_payload, serialized_tags)
|
|
96
|
+
end
|
|
114
97
|
end
|
|
115
|
-
rescue Error::AgentCommunicationError
|
|
116
|
-
raise
|
|
117
|
-
# Datadog::Core::Transport does not perform any exception mapping,
|
|
118
|
-
# therefore we could have any exception here from failure to parse
|
|
119
|
-
# agent URI for example.
|
|
120
|
-
# If we ever implement retries for network errors, we should distinguish
|
|
121
|
-
# actual network errors from non-network errors that are raised by
|
|
122
|
-
# transport code.
|
|
123
|
-
rescue => exc
|
|
124
|
-
raise Error::AgentCommunicationError, "send_input failed: #{exc.class}: #{exc}"
|
|
125
98
|
end
|
|
126
99
|
end
|
|
127
100
|
end
|
data/lib/datadog/di.rb
CHANGED
|
@@ -9,16 +9,13 @@ module Datadog
|
|
|
9
9
|
#
|
|
10
10
|
# @api private
|
|
11
11
|
module DI
|
|
12
|
+
INSTRUMENTED_COUNTERS_LOCK = Mutex.new
|
|
13
|
+
|
|
12
14
|
class << self
|
|
13
15
|
def enabled?
|
|
14
16
|
Datadog.configuration.dynamic_instrumentation.enabled
|
|
15
17
|
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Expose DI to global shared objects
|
|
19
|
-
Extensions.activate!
|
|
20
18
|
|
|
21
|
-
class << self
|
|
22
19
|
# This method is called from DI Remote handler to issue DI operations
|
|
23
20
|
# to the probe manager (add or remove probes).
|
|
24
21
|
#
|
|
@@ -31,6 +28,65 @@ module Datadog
|
|
|
31
28
|
def component
|
|
32
29
|
Datadog.send(:components).dynamic_instrumentation
|
|
33
30
|
end
|
|
31
|
+
|
|
32
|
+
# Track how many outstanding instrumentations are in DI.
|
|
33
|
+
#
|
|
34
|
+
# It is hard to find the actual instrumentations - there is no
|
|
35
|
+
# method provided by Ruby to list all trace points, and we would
|
|
36
|
+
# need to manually track our instrumentation modules for method probes.
|
|
37
|
+
# Plus, tracking the modules could create active references to
|
|
38
|
+
# instrumentation, which is not desired.
|
|
39
|
+
#
|
|
40
|
+
# A simpler solution is to maintain a counter which is increased
|
|
41
|
+
# whenever a probe is installed and decreased when a probe is removed.
|
|
42
|
+
#
|
|
43
|
+
# This counter does not include pending probes - being not installed,
|
|
44
|
+
# those pose no concerns to customer applications.
|
|
45
|
+
def instrumented_count(kind = nil)
|
|
46
|
+
INSTRUMENTED_COUNTERS_LOCK.synchronize do
|
|
47
|
+
if defined?(@instrumented_count)
|
|
48
|
+
if kind
|
|
49
|
+
validate_kind!(kind)
|
|
50
|
+
@instrumented_count[kind] || 0
|
|
51
|
+
else
|
|
52
|
+
@instrumented_count.inject(0) do |sum, (_kind, count)|
|
|
53
|
+
sum + count
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
0
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def instrumented_count_inc(kind)
|
|
63
|
+
validate_kind!(kind)
|
|
64
|
+
INSTRUMENTED_COUNTERS_LOCK.synchronize do
|
|
65
|
+
@instrumented_count = Hash.new(0) unless defined?(@instrumented_count)
|
|
66
|
+
@instrumented_count[kind] += 1
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def instrumented_count_dec(kind)
|
|
71
|
+
validate_kind!(kind)
|
|
72
|
+
INSTRUMENTED_COUNTERS_LOCK.synchronize do
|
|
73
|
+
@instrumented_count = Hash.new(0) unless defined?(@instrumented_count)
|
|
74
|
+
if @instrumented_count[kind] <= 0
|
|
75
|
+
Datadog.logger.debug { "di: attempting to decrease instrumented count below zero for #{kind}" }
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
@instrumented_count[kind] -= 1
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private def validate_kind!(kind)
|
|
83
|
+
unless %i[line method].include?(kind)
|
|
84
|
+
raise ArgumentError, "Invalid kind: #{kind}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
34
87
|
end
|
|
88
|
+
|
|
89
|
+
# Expose DI to global shared objects
|
|
90
|
+
Extensions.activate!
|
|
35
91
|
end
|
|
36
92
|
end
|
|
@@ -18,10 +18,10 @@ module Datadog
|
|
|
18
18
|
regex_match = regex.match(file_path)
|
|
19
19
|
return unless regex_match
|
|
20
20
|
|
|
21
|
-
gem_name = regex_match[1]
|
|
21
|
+
gem_name = regex_match[1] #: String
|
|
22
22
|
|
|
23
23
|
begin
|
|
24
|
-
Gem::Specification.find_by_name(gem_name)
|
|
24
|
+
Gem::Specification.find_by_name(gem_name)
|
|
25
25
|
rescue Gem::MissingSpecError
|
|
26
26
|
nil
|
|
27
27
|
end
|
|
@@ -66,8 +66,7 @@ module Datadog
|
|
|
66
66
|
record_event_telemetry_metric(LOGIN_SUCCESS_EVENT)
|
|
67
67
|
::Datadog::AppSec::Instrumentation.gateway.push('appsec.events.user_lifecycle', LOGIN_SUCCESS_EVENT)
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
return Kit::Identity.set_user(trace, span, **user_attributes) if user_attributes.key?(:id) # steep:ignore
|
|
69
|
+
return Kit::Identity.set_user(trace, span, **user_attributes) if user_attributes.key?(:id)
|
|
71
70
|
|
|
72
71
|
# NOTE: This is a fallback for the case when we don't have an ID,
|
|
73
72
|
# but need to trigger WAF.
|
|
@@ -156,7 +155,7 @@ module Datadog
|
|
|
156
155
|
raise ArgumentError, 'missing required user key `:id`' unless user_or_id.key?(:id)
|
|
157
156
|
raise TypeError, 'user key `:id` must be a String' unless user_or_id[:id].is_a?(String)
|
|
158
157
|
|
|
159
|
-
user_or_id.merge(login: login)
|
|
158
|
+
user_or_id.merge(login: login) #: {login: ::String, ?id: ::String?}
|
|
160
159
|
else
|
|
161
160
|
raise TypeError, '`user_or_id` argument must be either String or Hash'
|
|
162
161
|
end
|
|
@@ -9,7 +9,8 @@ module Datadog
|
|
|
9
9
|
module OpenFeature
|
|
10
10
|
# This class performs the evaluation of the feature flag
|
|
11
11
|
class EvaluationEngine
|
|
12
|
-
|
|
12
|
+
# Steep: https://github.com/soutaro/steep/issues/1880
|
|
13
|
+
ReconfigurationError = Class.new(StandardError) # steep:ignore IncompatibleAssignment
|
|
13
14
|
|
|
14
15
|
ALLOWED_TYPES = %i[boolean string number float integer object].freeze
|
|
15
16
|
|
|
@@ -6,8 +6,6 @@ module Datadog
|
|
|
6
6
|
module OpenFeature
|
|
7
7
|
# This module contains the remote configuration functionality for OpenFeature
|
|
8
8
|
module Remote
|
|
9
|
-
ReadError = Class.new(StandardError)
|
|
10
|
-
|
|
11
9
|
class << self
|
|
12
10
|
FFE_FLAG_CONFIGURATION_RULES = 1 << 46
|
|
13
11
|
FFE_PRODUCTS = ['FFE_FLAGS'].freeze
|
|
@@ -42,8 +40,6 @@ module Datadog
|
|
|
42
40
|
# @type var content: Core::Remote::Configuration::Content
|
|
43
41
|
engine.reconfigure!(read_content(content))
|
|
44
42
|
content.applied
|
|
45
|
-
rescue ReadError => e
|
|
46
|
-
content.errored("Error reading Remote Configuration content: #{e.message}")
|
|
47
43
|
rescue EvaluationEngine::ReconfigurationError => e
|
|
48
44
|
content.errored("Error applying OpenFeature configuration: #{e.message}")
|
|
49
45
|
end
|
|
@@ -61,12 +57,9 @@ module Datadog
|
|
|
61
57
|
private
|
|
62
58
|
|
|
63
59
|
def read_content(content)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
raise ReadError, 'EOF reached' if data.nil?
|
|
68
|
-
|
|
69
|
-
data
|
|
60
|
+
# Unlike all of the other remotes, this one does not JSON-parse
|
|
61
|
+
# the data.
|
|
62
|
+
content.data
|
|
70
63
|
end
|
|
71
64
|
end
|
|
72
65
|
end
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../core/encoding'
|
|
3
4
|
require_relative '../core/transport/http'
|
|
4
5
|
require_relative '../core/transport/http/env'
|
|
6
|
+
require_relative '../core/transport/http/api/endpoint'
|
|
7
|
+
require_relative '../core/transport/http/api/instance'
|
|
5
8
|
require_relative '../core/transport/parcel'
|
|
6
9
|
require_relative '../core/transport/request'
|
|
7
10
|
|
|
@@ -17,15 +20,14 @@ module Datadog
|
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
class HTTP
|
|
20
|
-
class Spec
|
|
23
|
+
class Spec
|
|
21
24
|
def initialize
|
|
22
25
|
@endpoint = Core::Transport::HTTP::API::Endpoint.new(
|
|
23
26
|
:post, '/evp_proxy/v2/api/v2/exposures'
|
|
24
27
|
)
|
|
25
|
-
|
|
26
|
-
super
|
|
27
28
|
end
|
|
28
29
|
|
|
30
|
+
# TODO rename to send_request?
|
|
29
31
|
def call(env, &block)
|
|
30
32
|
@endpoint.call(env) do |request_env|
|
|
31
33
|
request_env.headers['Content-Type'] = Core::Encoding::JSONEncoder.content_type
|
|
@@ -37,15 +39,8 @@ module Datadog
|
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
|
|
40
|
-
class Instance < Core::Transport::HTTP::API::Instance
|
|
41
|
-
def send_exposures(env)
|
|
42
|
-
@spec.call(env) { |request_env| call(request_env) }
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
42
|
def self.build(agent_settings:, logger:)
|
|
47
43
|
Core::Transport::HTTP.build(
|
|
48
|
-
api_instance_class: HTTP::Instance,
|
|
49
44
|
agent_settings: agent_settings,
|
|
50
45
|
logger: logger
|
|
51
46
|
) { |t| t.api('exposures', HTTP::Spec.new) }.to_transport(self)
|
|
@@ -58,7 +53,10 @@ module Datadog
|
|
|
58
53
|
|
|
59
54
|
def send_exposures(payload)
|
|
60
55
|
request = Core::Transport::Request.new(EncodedParcel.new(payload))
|
|
61
|
-
|
|
56
|
+
|
|
57
|
+
@api.endpoint.call(Core::Transport::HTTP::Env.new(request)) do |env|
|
|
58
|
+
@api.call(env)
|
|
59
|
+
end
|
|
62
60
|
rescue => e
|
|
63
61
|
message = "Internal error during request. Cause: #{e.class.name} #{e.message} " \
|
|
64
62
|
"Location: #{Array(e.backtrace).first}"
|
|
@@ -140,13 +140,13 @@ module Datadog
|
|
|
140
140
|
option :timeout_millis do |o|
|
|
141
141
|
o.type :int, nilable: true
|
|
142
142
|
o.env 'OTEL_EXPORTER_OTLP_METRICS_TIMEOUT'
|
|
143
|
-
o.default
|
|
143
|
+
o.default 10000
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
option :protocol do |o|
|
|
147
147
|
o.type :string, nilable: true
|
|
148
148
|
o.env 'OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'
|
|
149
|
-
o.default
|
|
149
|
+
o.default "http/protobuf"
|
|
150
150
|
o.setter(&Settings.normalize_protocol('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'))
|
|
151
151
|
end
|
|
152
152
|
end
|
|
@@ -70,12 +70,7 @@ module Datadog
|
|
|
70
70
|
@logger.warn("Failed to configure OTLP metrics exporter: #{e.class}: #{e}")
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def
|
|
74
|
-
metrics_config = @settings.opentelemetry.metrics
|
|
75
|
-
exporter_config = @settings.opentelemetry.exporter
|
|
76
|
-
|
|
77
|
-
return metrics_config.endpoint if metrics_config.endpoint
|
|
78
|
-
return exporter_config.endpoint if exporter_config.endpoint
|
|
73
|
+
def default_metrics_endpoint
|
|
79
74
|
"#{@agent_ssl ? "https" : "http"}://#{@agent_host}:4318/v1/metrics"
|
|
80
75
|
end
|
|
81
76
|
|
|
@@ -84,16 +79,19 @@ module Datadog
|
|
|
84
79
|
require_relative 'sdk/metrics_exporter'
|
|
85
80
|
|
|
86
81
|
metrics_config = @settings.opentelemetry.metrics
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
endpoint = get_metrics_config_with_fallback(
|
|
83
|
+
option_name: :endpoint,
|
|
84
|
+
computed_default: default_metrics_endpoint
|
|
85
|
+
)
|
|
86
|
+
timeout = get_metrics_config_with_fallback(option_name: :timeout_millis)
|
|
87
|
+
headers = get_metrics_config_with_fallback(option_name: :headers)
|
|
88
|
+
# OpenTelemetry SDK only supports http/protobuf protocol.
|
|
89
|
+
# TODO: Add support for http/json and grpc.
|
|
90
|
+
# protocol = get_metrics_config_with_fallback(option_name: :protocol)
|
|
92
91
|
exporter = Datadog::OpenTelemetry::SDK::MetricsExporter.new(
|
|
93
|
-
endpoint:
|
|
92
|
+
endpoint: endpoint,
|
|
94
93
|
timeout: timeout / 1000.0,
|
|
95
|
-
headers: headers
|
|
96
|
-
protocol: protocol
|
|
94
|
+
headers: headers
|
|
97
95
|
)
|
|
98
96
|
|
|
99
97
|
reader = ::OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(
|
|
@@ -105,6 +103,15 @@ module Datadog
|
|
|
105
103
|
rescue LoadError => e
|
|
106
104
|
@logger.warn("Could not load OTLP metrics exporter: #{e.class}: #{e}")
|
|
107
105
|
end
|
|
106
|
+
|
|
107
|
+
# Returns metrics config value if explicitly set, otherwise falls back to exporter config or computed default value.
|
|
108
|
+
def get_metrics_config_with_fallback(option_name:, computed_default: nil)
|
|
109
|
+
if @settings.opentelemetry.metrics.using_default?(option_name)
|
|
110
|
+
@settings.opentelemetry.exporter.public_send(option_name) || computed_default
|
|
111
|
+
else
|
|
112
|
+
@settings.opentelemetry.metrics.public_send(option_name)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
108
115
|
end
|
|
109
116
|
end
|
|
110
117
|
end
|
|
@@ -9,21 +9,18 @@ module Datadog
|
|
|
9
9
|
METRIC_EXPORT_ATTEMPTS = 'otel.metrics_export_attempts'
|
|
10
10
|
METRIC_EXPORT_SUCCESSES = 'otel.metrics_export_successes'
|
|
11
11
|
METRIC_EXPORT_FAILURES = 'otel.metrics_export_failures'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
super(endpoint: endpoint, timeout: timeout, headers: headers)
|
|
15
|
-
@telemetry_tags = {'protocol' => protocol, 'encoding' => 'protobuf'}
|
|
16
|
-
end
|
|
12
|
+
TELEMETRY_NAMESPACE = 'tracers'
|
|
13
|
+
TELEMETRY_TAGS = {'protocol' => "http", 'encoding' => 'protobuf'}
|
|
17
14
|
|
|
18
15
|
def export(metrics, timeout: nil)
|
|
19
|
-
telemetry&.inc(
|
|
16
|
+
telemetry&.inc(TELEMETRY_NAMESPACE, METRIC_EXPORT_ATTEMPTS, 1, tags: TELEMETRY_TAGS)
|
|
20
17
|
result = super
|
|
21
18
|
metric_name = (result == 0) ? METRIC_EXPORT_SUCCESSES : METRIC_EXPORT_FAILURES
|
|
22
|
-
telemetry&.inc(
|
|
19
|
+
telemetry&.inc(TELEMETRY_NAMESPACE, metric_name, 1, tags: TELEMETRY_TAGS)
|
|
23
20
|
result
|
|
24
21
|
rescue => e
|
|
25
22
|
Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e}")
|
|
26
|
-
telemetry&.inc(
|
|
23
|
+
telemetry&.inc(TELEMETRY_NAMESPACE, METRIC_EXPORT_FAILURES, 1, tags: TELEMETRY_TAGS)
|
|
27
24
|
raise
|
|
28
25
|
end
|
|
29
26
|
|
|
@@ -22,7 +22,7 @@ module Datadog
|
|
|
22
22
|
@libraries_by_path = {}
|
|
23
23
|
@seen_files = Set.new
|
|
24
24
|
@seen_libraries = Set.new
|
|
25
|
-
@executable_paths = [Gem.bindir,
|
|
25
|
+
@executable_paths = [Gem.bindir, bundler_bin_path].uniq.compact.freeze
|
|
26
26
|
|
|
27
27
|
record_library(
|
|
28
28
|
Library.new(
|
|
@@ -116,6 +116,30 @@ module Datadog
|
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
+
# This is intended to mirror bundler's `Bundler.bin_path` with one key difference: the bundler version of the
|
|
120
|
+
# method **tries to create the path** if it doesn't exist, whereas our version doesn't.
|
|
121
|
+
#
|
|
122
|
+
# This "try to create the path" is annoying because creating the path can fail if e.g. the app doesn't have
|
|
123
|
+
# permissions to do that, see https://github.com/DataDog/dd-trace-rb/issues/5137.
|
|
124
|
+
# Thus we have our own version that a) Avoids creating the path, and b) Rescues exceptions to avoid any
|
|
125
|
+
# bundler complaints here impacting the application. (Bundler tends to go "something is wrong, raise!" which
|
|
126
|
+
# I think makes a lot of sense given how bundler is intended to be used, but for this our kind of "ask a few
|
|
127
|
+
# questions usage" it's not what we want.)
|
|
128
|
+
def bundler_bin_path
|
|
129
|
+
return unless defined?(Bundler)
|
|
130
|
+
|
|
131
|
+
path = Bundler.settings[:bin] || "bin"
|
|
132
|
+
root = Bundler.root
|
|
133
|
+
result = Pathname.new(path).expand_path(root).expand_path
|
|
134
|
+
result.to_s
|
|
135
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
136
|
+
Datadog.logger.debug(
|
|
137
|
+
"CodeProvenance#bundler_bin_path failed. " \
|
|
138
|
+
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
|
139
|
+
)
|
|
140
|
+
nil
|
|
141
|
+
end
|
|
142
|
+
|
|
119
143
|
# Represents metadata we have for a ruby gem
|
|
120
144
|
#
|
|
121
145
|
# Important note: This class gets encoded to JSON with the built-in JSON gem. But, we've found that in some
|
|
@@ -137,7 +161,8 @@ module Datadog
|
|
|
137
161
|
end
|
|
138
162
|
|
|
139
163
|
def to_json(arg = nil)
|
|
140
|
-
|
|
164
|
+
# Steep: https://github.com/ruby/rbs/pull/2691 (remove after RBS 4.0 release)
|
|
165
|
+
{kind: @kind, name: @name, version: @version, paths: @paths}.to_json(arg) # steep:ignore ArgumentTypeMismatch
|
|
141
166
|
end
|
|
142
167
|
|
|
143
168
|
def path
|
|
@@ -16,7 +16,9 @@ module Datadog
|
|
|
16
16
|
class Info
|
|
17
17
|
def initialize(settings)
|
|
18
18
|
@profiler_info = nil
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
# Steep: https://github.com/soutaro/steep/issues/363
|
|
21
|
+
@info = { # steep:ignore IncompatibleAssignment
|
|
20
22
|
platform: collect_platform_info,
|
|
21
23
|
runtime: collect_runtime_info,
|
|
22
24
|
application: collect_application_info(settings),
|
|
@@ -96,7 +98,7 @@ module Datadog
|
|
|
96
98
|
end
|
|
97
99
|
|
|
98
100
|
def collect_profiler_info(settings)
|
|
99
|
-
|
|
101
|
+
@profiler_info ||= begin
|
|
100
102
|
lib_datadog_gem = ::Gem.loaded_specs["libdatadog"]
|
|
101
103
|
|
|
102
104
|
libdatadog_version =
|
|
@@ -108,13 +110,12 @@ module Datadog
|
|
|
108
110
|
"#{Libdatadog::VERSION}-(unknown)"
|
|
109
111
|
end
|
|
110
112
|
|
|
111
|
-
|
|
113
|
+
{
|
|
112
114
|
version: Datadog::Core::Environment::Identity.gem_datadog_version,
|
|
113
115
|
libdatadog: libdatadog_version,
|
|
114
116
|
settings: collect_settings_recursively(settings.profiling),
|
|
115
117
|
}.freeze
|
|
116
118
|
end
|
|
117
|
-
@profiler_info
|
|
118
119
|
end
|
|
119
120
|
|
|
120
121
|
# The settings/option model isn't directly serializable because
|