datadog 2.31.0 → 2.33.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/ext/datadog_profiling_native_extension/clock_id.h +9 -1
- data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +73 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +17 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -5
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +6 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +8 -4
- data/ext/datadog_profiling_native_extension/http_transport.c +10 -5
- data/ext/datadog_profiling_native_extension/stack_recorder.c +3 -9
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
- data/ext/libdatadog_api/crashtracker.c +2 -0
- data/ext/libdatadog_api/di.c +48 -0
- data/ext/libdatadog_api/extconf.rb +7 -4
- data/ext/libdatadog_extconf_helpers.rb +38 -1
- data/lib/datadog/ai_guard/autoload.rb +10 -0
- data/lib/datadog/ai_guard/component.rb +1 -1
- data/lib/datadog/ai_guard/configuration.rb +105 -2
- data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
- data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
- data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +83 -0
- data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
- data/lib/datadog/ai_guard/evaluation.rb +2 -0
- data/lib/datadog/ai_guard/ext.rb +2 -0
- data/lib/datadog/ai_guard.rb +8 -0
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +1 -1
- data/lib/datadog/appsec/configuration.rb +414 -1
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
- data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
- data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +111 -0
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
- data/lib/datadog/appsec/metrics/telemetry.rb +13 -1
- data/lib/datadog/appsec/security_engine/runner.rb +1 -1
- data/lib/datadog/appsec/trace_keeper.rb +18 -6
- data/lib/datadog/appsec/utils/http/url_encoded.rb +2 -2
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +13 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +4 -0
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/contrib/rails/utils.rb +1 -1
- data/lib/datadog/core/crashtracking/component.rb +3 -3
- data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/core/environment/container.rb +2 -2
- data/lib/datadog/core/environment/ext.rb +1 -0
- data/lib/datadog/core/environment/socket.rb +13 -0
- data/lib/datadog/core/feature_flags.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +5 -5
- data/lib/datadog/core/remote/client.rb +1 -1
- data/lib/datadog/core/remote/component.rb +2 -2
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/emitter.rb +1 -1
- data/lib/datadog/core/telemetry/event/app_started.rb +2 -2
- data/lib/datadog/core/transport/http.rb +2 -0
- data/lib/datadog/core/utils.rb +1 -1
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core.rb +1 -1
- data/lib/datadog/data_streams/configuration.rb +40 -1
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +1 -1
- data/lib/datadog/data_streams.rb +1 -1
- data/lib/datadog/di/base.rb +8 -5
- data/lib/datadog/di/code_tracker.rb +179 -1
- data/lib/datadog/di/component.rb +1 -1
- data/lib/datadog/di/configuration.rb +235 -2
- data/lib/datadog/di/instrumenter.rb +46 -26
- data/lib/datadog/di/probe_builder.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +2 -2
- data/lib/datadog/di/probe_manager.rb +6 -6
- data/lib/datadog/di/probe_notification_builder.rb +1 -1
- data/lib/datadog/di/probe_notifier_worker.rb +2 -2
- data/lib/datadog/di/remote.rb +6 -6
- data/lib/datadog/di/serializer.rb +1 -1
- data/lib/datadog/di/transport/input.rb +3 -3
- data/lib/datadog/error_tracking/configuration.rb +55 -2
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/open_feature/component.rb +18 -1
- data/lib/datadog/open_feature/evaluation_engine.rb +3 -3
- data/lib/datadog/open_feature/exposures/reporter.rb +1 -1
- data/lib/datadog/open_feature/exposures/worker.rb +1 -1
- data/lib/datadog/open_feature/hooks/flag_eval_hook.rb +49 -0
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
- data/lib/datadog/open_feature/provider.rb +19 -1
- data/lib/datadog/open_feature/remote.rb +1 -1
- data/lib/datadog/open_feature/transport.rb +1 -1
- data/lib/datadog/opentelemetry/metrics.rb +13 -4
- data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +1 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +35 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +31 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +8 -2
- data/lib/datadog/profiling/collectors/info.rb +16 -3
- data/lib/datadog/profiling/component.rb +3 -6
- data/lib/datadog/profiling/exporter.rb +37 -12
- data/lib/datadog/profiling/ext.rb +0 -2
- data/lib/datadog/profiling/flush.rb +21 -12
- data/lib/datadog/profiling/http_transport.rb +12 -1
- data/lib/datadog/profiling/load_native_extension.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +13 -1
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/stack_recorder.rb +0 -4
- data/lib/datadog/profiling/tasks/exec.rb +8 -3
- data/lib/datadog/profiling/tasks/help.rb +1 -0
- data/lib/datadog/profiling/tasks/setup.rb +2 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/symbol_database/configuration.rb +65 -0
- data/lib/datadog/symbol_database/extractor.rb +906 -0
- data/lib/datadog/symbol_database/file_hash.rb +46 -0
- data/lib/datadog/symbol_database/logger.rb +43 -0
- data/lib/datadog/symbol_database/scope.rb +102 -0
- data/lib/datadog/symbol_database/scope_batcher.rb +280 -0
- data/lib/datadog/symbol_database/service_version.rb +57 -0
- data/lib/datadog/symbol_database/symbol.rb +66 -0
- data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
- data/lib/datadog/symbol_database/transport/http.rb +45 -0
- data/lib/datadog/symbol_database/transport.rb +54 -0
- data/lib/datadog/symbol_database/uploader.rb +169 -0
- data/lib/datadog/symbol_database.rb +49 -0
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -3
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/component.rb +1 -1
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +7 -4
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/extensions.rb +9 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +5 -5
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +2 -2
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -2
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +3 -3
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/rack/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +117 -1
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
- data/lib/datadog/tracing/contrib.rb +8 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/tracing/distributed/baggage.rb +59 -5
- data/lib/datadog/tracing/distributed/datadog.rb +11 -11
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -1
- data/lib/datadog/tracing/distributed/propagation.rb +2 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +74 -32
- data/lib/datadog/tracing/event.rb +1 -1
- data/lib/datadog/tracing/metadata/tagging.rb +2 -2
- data/lib/datadog/tracing/pipeline.rb +1 -1
- data/lib/datadog/tracing/remote.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +3 -3
- data/lib/datadog/tracing/trace_operation.rb +4 -4
- data/lib/datadog/tracing/tracer.rb +6 -8
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/workers.rb +2 -1
- data/lib/datadog/version.rb +1 -1
- metadata +33 -12
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
- data/lib/datadog/ai_guard/configuration/settings.rb +0 -113
- data/lib/datadog/appsec/configuration/settings.rb +0 -423
- data/lib/datadog/data_streams/configuration/settings.rb +0 -49
- data/lib/datadog/di/configuration/settings.rb +0 -243
- data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
|
@@ -1,11 +1,114 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "uri"
|
|
4
|
+
require_relative "configuration/ext"
|
|
5
|
+
|
|
3
6
|
module Datadog
|
|
4
7
|
module AIGuard
|
|
5
8
|
# Configuration module for AI Guard
|
|
6
9
|
module Configuration
|
|
10
|
+
# AI Guard specific settings
|
|
11
|
+
module Settings
|
|
12
|
+
def self.extended(base)
|
|
13
|
+
base = base.singleton_class unless base.is_a?(Class)
|
|
14
|
+
add_settings!(base)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.add_settings!(base)
|
|
18
|
+
base.class_eval do
|
|
19
|
+
# AI Guard specific configurations.
|
|
20
|
+
# @public_api
|
|
21
|
+
#
|
|
22
|
+
# Steep does not update `self` for this `class_eval` block.
|
|
23
|
+
# @type self: Datadog::Core::Configuration::Base::_DslContext
|
|
24
|
+
settings :ai_guard do
|
|
25
|
+
# Enable AI Guard.
|
|
26
|
+
#
|
|
27
|
+
# You can use this option to skip calls to AI Guard API without having to remove library as a whole.
|
|
28
|
+
#
|
|
29
|
+
# @default `DD_AI_GUARD_ENABLED`, otherwise `false`
|
|
30
|
+
# @return [Boolean]
|
|
31
|
+
option :enabled do |o|
|
|
32
|
+
o.type :bool
|
|
33
|
+
o.env Ext::ENV_AI_GUARD_ENABLED
|
|
34
|
+
o.default false
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
define_method(:instrument) do |integration_name|
|
|
38
|
+
return unless enabled # steep:ignore
|
|
39
|
+
|
|
40
|
+
if (registered_integration = Datadog::AIGuard::Contrib::Integration.registry[integration_name])
|
|
41
|
+
klass = registered_integration.klass
|
|
42
|
+
if klass.loaded? && klass.compatible?
|
|
43
|
+
instance = klass.new
|
|
44
|
+
instance.patcher.patch unless instance.patcher.patched?
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# AI Guard API endpoint path.
|
|
50
|
+
#
|
|
51
|
+
# @default `DD_AI_GUARD_ENDPOINT`, otherwise `nil`
|
|
52
|
+
# @return [String, nil]
|
|
53
|
+
option :endpoint do |o|
|
|
54
|
+
o.type :string, nilable: true
|
|
55
|
+
o.env Ext::ENV_AI_GUARD_ENDPOINT
|
|
56
|
+
|
|
57
|
+
o.setter do |value|
|
|
58
|
+
next unless value
|
|
59
|
+
|
|
60
|
+
uri = URI(value.to_s)
|
|
61
|
+
raise ArgumentError, "Please provide an absolute URI that includes a protocol" unless uri.absolute?
|
|
62
|
+
|
|
63
|
+
uri.to_s.delete_suffix("/")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Datadog Application key.
|
|
68
|
+
#
|
|
69
|
+
# @default `DD_APP_KEY` environment variable, otherwise `nil`
|
|
70
|
+
# @return [String, nil]
|
|
71
|
+
option :app_key do |o|
|
|
72
|
+
o.type :string, nilable: true
|
|
73
|
+
o.env Ext::ENV_APP_KEY
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Request timeout in milliseconds.
|
|
77
|
+
#
|
|
78
|
+
# @default `DD_AI_GUARD_TIMEOUT`, otherwise 10 000 ms
|
|
79
|
+
# @return [Integer]
|
|
80
|
+
option :timeout_ms do |o|
|
|
81
|
+
o.type :int
|
|
82
|
+
o.env Ext::ENV_AI_GUARD_TIMEOUT
|
|
83
|
+
o.default 10_000
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Maximum content size in bytes.
|
|
87
|
+
# Content that exceeds the maximum allowed size is truncated before
|
|
88
|
+
# being stored in the current span context.
|
|
89
|
+
#
|
|
90
|
+
# @default `DD_AI_GUARD_MAX_CONTENT_SIZE`, otherwise 524 228 bytes
|
|
91
|
+
# @return [Integer]
|
|
92
|
+
option :max_content_size_bytes do |o|
|
|
93
|
+
o.type :int
|
|
94
|
+
o.env Ext::ENV_AI_GUARD_MAX_CONTENT_SIZE
|
|
95
|
+
o.default 512 * 1024
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Maximum number of messages.
|
|
99
|
+
# Older messages are omitted once the message limit is reached.
|
|
100
|
+
#
|
|
101
|
+
# @default `DD_AI_GUARD_MAX_MESSAGES_LENGTH`, otherwise 16 messages
|
|
102
|
+
# @return [Integer]
|
|
103
|
+
option :max_messages_length do |o|
|
|
104
|
+
o.type :int
|
|
105
|
+
o.env Ext::ENV_AI_GUARD_MAX_MESSAGES_LENGTH
|
|
106
|
+
o.default 16
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
7
112
|
end
|
|
8
113
|
end
|
|
9
114
|
end
|
|
10
|
-
|
|
11
|
-
require_relative "configuration/settings"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Contrib
|
|
6
|
+
# Auto-instrumentation for AI Guard integrations
|
|
7
|
+
module AutoInstrument
|
|
8
|
+
def self.patch_all
|
|
9
|
+
integrations = []
|
|
10
|
+
|
|
11
|
+
Datadog::AIGuard::Contrib::Integration.registry.each_value do |integration|
|
|
12
|
+
next unless integration.klass.auto_instrument?
|
|
13
|
+
|
|
14
|
+
integrations << integration.name
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
integrations.each do |integration_name|
|
|
18
|
+
Datadog.configuration.ai_guard.instrument(integration_name)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../integration"
|
|
4
|
+
require_relative "patcher"
|
|
5
|
+
require_relative "request_middleware"
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module AIGuard
|
|
9
|
+
module Contrib
|
|
10
|
+
module Rack
|
|
11
|
+
# Rack integration for AI Guard
|
|
12
|
+
class Integration
|
|
13
|
+
include Datadog::AIGuard::Contrib::Integration
|
|
14
|
+
|
|
15
|
+
MINIMUM_VERSION = Gem::Version.new("1.1.0")
|
|
16
|
+
|
|
17
|
+
register_as :rack, auto_patch: false
|
|
18
|
+
|
|
19
|
+
def self.version
|
|
20
|
+
Gem.loaded_specs["rack"]&.version
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.loaded?
|
|
24
|
+
!defined?(::Rack).nil?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.compatible?
|
|
28
|
+
super && !!(version&.>= MINIMUM_VERSION)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.auto_instrument?
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def patcher
|
|
36
|
+
Patcher
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Contrib
|
|
6
|
+
module Rack
|
|
7
|
+
# Patcher for Rack integration
|
|
8
|
+
module Patcher
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def patched?
|
|
12
|
+
!!Patcher.instance_variable_get(:@patched)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def target_version
|
|
16
|
+
Integration.version
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def patch
|
|
20
|
+
Patcher.instance_variable_set(:@patched, true)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../../tracing/client_ip"
|
|
4
|
+
require_relative "../../../tracing/contrib/rack/header_collection"
|
|
5
|
+
require_relative "../../../tracing/metadata/ext"
|
|
6
|
+
require_relative "../../ext"
|
|
7
|
+
|
|
8
|
+
module Datadog
|
|
9
|
+
module AIGuard
|
|
10
|
+
module Contrib
|
|
11
|
+
module Rack
|
|
12
|
+
# AI Guard Rack middleware.
|
|
13
|
+
#
|
|
14
|
+
# Inserted into the middleware stack right after
|
|
15
|
+
# Datadog::Tracing::Contrib::Rack::TraceMiddleware (i.e. nested inside
|
|
16
|
+
# it). This ordering matters: on the way out of the request, AI Guard's
|
|
17
|
+
# `ensure` block unwinds *before* Tracing's ensure, while Tracing's
|
|
18
|
+
# request span is still live. We need that, because Tracing's ensure
|
|
19
|
+
# calls `request_span.finish`, which builds a frozen `Span` snapshot of
|
|
20
|
+
# the meta hash — any `set_tag` call after that point mutates the
|
|
21
|
+
# `SpanOperation` but never reaches the exported `Span`.
|
|
22
|
+
#
|
|
23
|
+
# So while the span is still active, we tag `http.client_ip` and
|
|
24
|
+
# `network.client.ip` on it — but only when an AI Guard span was
|
|
25
|
+
# actually recorded during the request.
|
|
26
|
+
class RequestMiddleware
|
|
27
|
+
NETWORK_CLIENT_IP_TAG = "network.client.ip"
|
|
28
|
+
|
|
29
|
+
def initialize(app, opt = {})
|
|
30
|
+
@app = app
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def call(env)
|
|
34
|
+
@app.call(env)
|
|
35
|
+
ensure
|
|
36
|
+
tag_client_ip(env) if consume_ai_guard_executed_flag
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# AI Guard's evaluation flow sets `ai_guard.executed` on the trace
|
|
42
|
+
# whenever an AI Guard span is created during the request. We read
|
|
43
|
+
# it here to know whether to tag client IP, then clear it so the
|
|
44
|
+
# internal flag does not propagate to the exported trace.
|
|
45
|
+
#
|
|
46
|
+
# `Tracing.active_trace` is publicly typed as `TraceSegment?` but at
|
|
47
|
+
# runtime returns a `TraceOperation`, which exposes `get_tag` and
|
|
48
|
+
# `clear_tag`. Pre-existing sig mismatch — hence the steep:ignore.
|
|
49
|
+
# steep:ignore:start
|
|
50
|
+
def consume_ai_guard_executed_flag
|
|
51
|
+
trace = Datadog::Tracing.active_trace
|
|
52
|
+
return false unless trace
|
|
53
|
+
return false unless trace.get_tag(Datadog::AIGuard::Ext::SERVICE_ENTRY_EXECUTED_TAG) == "1"
|
|
54
|
+
|
|
55
|
+
trace.clear_tag(Datadog::AIGuard::Ext::SERVICE_ENTRY_EXECUTED_TAG)
|
|
56
|
+
true
|
|
57
|
+
end
|
|
58
|
+
# steep:ignore:end
|
|
59
|
+
|
|
60
|
+
def tag_client_ip(env)
|
|
61
|
+
span = Datadog::Tracing.active_span
|
|
62
|
+
return unless span
|
|
63
|
+
|
|
64
|
+
if span.get_tag(Datadog::Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
|
|
65
|
+
headers = Datadog::Tracing::Contrib::Rack::Header::RequestHeaderCollection.new(env)
|
|
66
|
+
Datadog::Tracing::ClientIp.set_client_ip_tag!(
|
|
67
|
+
span,
|
|
68
|
+
headers: headers,
|
|
69
|
+
remote_ip: env["REMOTE_ADDR"]
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if env["REMOTE_ADDR"] && span.get_tag(NETWORK_CLIENT_IP_TAG).nil?
|
|
74
|
+
span.set_tag(NETWORK_CLIENT_IP_TAG, env["REMOTE_ADDR"])
|
|
75
|
+
end
|
|
76
|
+
rescue => e
|
|
77
|
+
Datadog::AIGuard.telemetry&.report(e, description: "AI Guard: failed to tag client IP on root span")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../integration"
|
|
4
|
+
require_relative "patcher"
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module AIGuard
|
|
8
|
+
module Contrib
|
|
9
|
+
module Rails
|
|
10
|
+
# Rails integration for AI Guard
|
|
11
|
+
class Integration
|
|
12
|
+
include Datadog::AIGuard::Contrib::Integration
|
|
13
|
+
|
|
14
|
+
MINIMUM_VERSION = Gem::Version.new("4")
|
|
15
|
+
|
|
16
|
+
register_as :rails, auto_patch: false
|
|
17
|
+
|
|
18
|
+
def self.version
|
|
19
|
+
Gem.loaded_specs["railties"]&.version
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.loaded?
|
|
23
|
+
!defined?(::Rails).nil?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.compatible?
|
|
27
|
+
super && !!(version&.>= MINIMUM_VERSION)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.auto_instrument?
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def patcher
|
|
35
|
+
Patcher
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../../core/utils/only_once"
|
|
4
|
+
require_relative "../rack/request_middleware"
|
|
5
|
+
require_relative "../../../tracing/contrib"
|
|
6
|
+
require_relative "../../../tracing/contrib/rack/middlewares"
|
|
7
|
+
|
|
8
|
+
module Datadog
|
|
9
|
+
module AIGuard
|
|
10
|
+
module Contrib
|
|
11
|
+
module Rails
|
|
12
|
+
# Patcher for AI Guard on Rails. Inserts the AI Guard Rack middleware
|
|
13
|
+
# right after the Tracing Rack middleware so the request span is
|
|
14
|
+
# already active when AI Guard tags the client IP.
|
|
15
|
+
module Patcher
|
|
16
|
+
BEFORE_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
|
|
17
|
+
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
def patched?
|
|
21
|
+
!!Patcher.instance_variable_get(:@patched)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def target_version
|
|
25
|
+
Integration.version
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def patch
|
|
29
|
+
patch_before_initialize
|
|
30
|
+
Patcher.instance_variable_set(:@patched, true)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def patch_before_initialize
|
|
34
|
+
::ActiveSupport.on_load(:before_initialize) do
|
|
35
|
+
Datadog::AIGuard::Contrib::Rails::Patcher.before_initialize(self)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def before_initialize(app)
|
|
40
|
+
BEFORE_INITIALIZE_ONLY_ONCE_PER_APP[app].run do
|
|
41
|
+
# Middleware must be added before the application is initialized.
|
|
42
|
+
# Otherwise the middleware stack will be frozen.
|
|
43
|
+
add_middleware(app) if Datadog.configuration.tracing[:rails][:middleware]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def add_middleware(app)
|
|
48
|
+
if include_middleware?(Datadog::Tracing::Contrib::Rack::TraceMiddleware, app)
|
|
49
|
+
app.middleware.insert_after(
|
|
50
|
+
Datadog::Tracing::Contrib::Rack::TraceMiddleware,
|
|
51
|
+
Datadog::AIGuard::Contrib::Rack::RequestMiddleware
|
|
52
|
+
)
|
|
53
|
+
else
|
|
54
|
+
app.middleware.insert_before(0, Datadog::AIGuard::Contrib::Rack::RequestMiddleware)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def include_middleware?(middleware, app)
|
|
59
|
+
found = false
|
|
60
|
+
|
|
61
|
+
# find tracer middleware reference in Rails::Configuration::MiddlewareStackProxy
|
|
62
|
+
app.middleware.instance_variable_get(:@operations).each do |operation|
|
|
63
|
+
args = case operation
|
|
64
|
+
when Array
|
|
65
|
+
# rails 5.2
|
|
66
|
+
_op, args = operation
|
|
67
|
+
args
|
|
68
|
+
when Proc
|
|
69
|
+
if operation.binding.local_variables.include?(:args)
|
|
70
|
+
# rails 6.0, 6.1
|
|
71
|
+
operation.binding.local_variable_get(:args)
|
|
72
|
+
else
|
|
73
|
+
# rails 7.0 uses ... to pass args
|
|
74
|
+
# steep:ignore:start
|
|
75
|
+
args_getter = Class.new do
|
|
76
|
+
def method_missing(_op, *args) # standard:disable Style/MissingRespondToMissing
|
|
77
|
+
args
|
|
78
|
+
end
|
|
79
|
+
end.new
|
|
80
|
+
# steep:ignore:end
|
|
81
|
+
operation.call(args_getter)
|
|
82
|
+
end
|
|
83
|
+
else
|
|
84
|
+
# unknown, pass through
|
|
85
|
+
[]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
found = true if args.include?(middleware)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
found
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -15,6 +15,8 @@ module Datadog
|
|
|
15
15
|
Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
|
16
16
|
Tracing::Sampling::Ext::Decision::AI_GUARD
|
|
17
17
|
)
|
|
18
|
+
trace.set_tag(Ext::EVENT_TAG, true)
|
|
19
|
+
trace.set_tag(Ext::SERVICE_ENTRY_EXECUTED_TAG, "1")
|
|
18
20
|
|
|
19
21
|
if (last_message = messages.last)
|
|
20
22
|
if last_message.tool_call
|
data/lib/datadog/ai_guard/ext.rb
CHANGED
data/lib/datadog/ai_guard.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require_relative "core/configuration"
|
|
4
4
|
require_relative "ai_guard/configuration"
|
|
5
5
|
|
|
6
|
+
require_relative "ai_guard/contrib/rack/integration"
|
|
7
|
+
require_relative "ai_guard/contrib/rails/integration"
|
|
6
8
|
require_relative "ai_guard/contrib/ruby_llm/integration"
|
|
7
9
|
|
|
8
10
|
module Datadog
|
|
@@ -50,6 +52,10 @@ module Datadog
|
|
|
50
52
|
Datadog.send(:components).ai_guard&.logger
|
|
51
53
|
end
|
|
52
54
|
|
|
55
|
+
def telemetry
|
|
56
|
+
Datadog.send(:components).ai_guard&.telemetry
|
|
57
|
+
end
|
|
58
|
+
|
|
53
59
|
# Evaluates one or more messages using AI Guard API.
|
|
54
60
|
#
|
|
55
61
|
# Example:
|
|
@@ -171,3 +177,5 @@ module Datadog
|
|
|
171
177
|
end
|
|
172
178
|
end
|
|
173
179
|
end
|
|
180
|
+
|
|
181
|
+
require_relative "ai_guard/autoload"
|
|
@@ -7,7 +7,7 @@ if %w[1 true].include?((Datadog::DATADOG_ENV['DD_APPSEC_ENABLED'] || '').downcas
|
|
|
7
7
|
rescue => e
|
|
8
8
|
Kernel.warn(
|
|
9
9
|
'[datadog] AppSec failed to instrument. No security check will be performed. error: ' \
|
|
10
|
-
" #{e.class}: #{e}"
|
|
10
|
+
" #{e.class}: #{e.message}"
|
|
11
11
|
)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -47,7 +47,7 @@ module Datadog
|
|
|
47
47
|
security_engine = SecurityEngine::Engine.new(appsec_settings: settings.appsec, telemetry: telemetry)
|
|
48
48
|
new(security_engine: security_engine)
|
|
49
49
|
rescue => e
|
|
50
|
-
Datadog.logger.warn("AppSec is disabled: #{e.class}: #{e}; there may be additional logged errors above")
|
|
50
|
+
Datadog.logger.warn("AppSec is disabled: #{e.class}: #{e.message}; there may be additional logged errors above")
|
|
51
51
|
|
|
52
52
|
# Not reporting to telemetry here because some of the rescued exceptions
|
|
53
53
|
# have already been reported by the code that raised them
|