datadog 2.29.0 → 2.31.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 +87 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +21 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +9 -7
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +18 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +6 -24
- data/ext/datadog_profiling_native_extension/heap_recorder.c +5 -6
- data/ext/datadog_profiling_native_extension/http_transport.c +51 -64
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
- data/ext/datadog_profiling_native_extension/profiling.c +3 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +24 -8
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -3
- data/ext/datadog_profiling_native_extension/stack_recorder.c +29 -43
- data/ext/libdatadog_api/crashtracker.c +5 -8
- data/ext/libdatadog_api/crashtracker_report_exception.c +34 -144
- data/ext/libdatadog_api/datadog_ruby_common.c +18 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/di.c +79 -0
- data/ext/libdatadog_api/extconf.rb +5 -20
- data/ext/libdatadog_api/init.c +5 -2
- data/ext/libdatadog_extconf_helpers.rb +57 -11
- data/lib/datadog/ai_guard/component.rb +2 -0
- data/lib/datadog/ai_guard/configuration/settings.rb +3 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +41 -3
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation/request.rb +14 -9
- data/lib/datadog/ai_guard/evaluation/result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation.rb +36 -7
- data/lib/datadog/ai_guard.rb +26 -8
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +11 -7
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +3 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/patcher.rb +2 -0
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +25 -2
- data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +2 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +3 -3
- data/lib/datadog/appsec/event.rb +1 -17
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
- data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -2
- data/lib/datadog/appsec/utils/http/media_type.rb +1 -2
- data/lib/datadog/appsec/utils/http/url_encoded.rb +2 -2
- data/lib/datadog/appsec.rb +5 -9
- data/lib/datadog/core/configuration/base.rb +17 -5
- data/lib/datadog/core/configuration/components.rb +21 -8
- data/lib/datadog/core/configuration/config_helper.rb +9 -0
- data/lib/datadog/core/configuration/option.rb +32 -6
- data/lib/datadog/core/configuration/option_definition.rb +38 -12
- data/lib/datadog/core/configuration/options.rb +41 -7
- data/lib/datadog/core/configuration/settings.rb +42 -3
- data/lib/datadog/core/configuration/supported_configurations.rb +17 -0
- data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
- data/lib/datadog/core/contrib/rails/utils.rb +7 -3
- data/lib/datadog/core/crashtracking/component.rb +7 -15
- data/lib/datadog/core/environment/container.rb +2 -2
- data/lib/datadog/core/environment/ext.rb +1 -0
- data/lib/datadog/core/environment/identity.rb +25 -3
- data/lib/datadog/core/environment/process.rb +12 -0
- data/lib/datadog/core/metrics/client.rb +5 -5
- data/lib/datadog/core/process_discovery.rb +5 -0
- data/lib/datadog/core/remote/component.rb +38 -21
- data/lib/datadog/core/runtime/metrics.rb +2 -3
- data/lib/datadog/core/telemetry/component.rb +3 -0
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
- data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +151 -169
- data/lib/datadog/core/telemetry/event.rb +1 -7
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -0
- data/lib/datadog/core/telemetry/worker.rb +20 -0
- data/lib/datadog/core/utils/base64.rb +1 -1
- data/lib/datadog/core/utils/only_once.rb +1 -1
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +36 -0
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core/workers/interval_loop.rb +13 -6
- data/lib/datadog/core/workers/queue.rb +0 -4
- data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
- data/lib/datadog/core.rb +0 -1
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +1 -0
- data/lib/datadog/di/boot.rb +3 -4
- data/lib/datadog/di/component.rb +20 -4
- data/lib/datadog/di/instrumenter.rb +20 -10
- data/lib/datadog/di/probe_manager.rb +79 -62
- data/lib/datadog/di/probe_notification_builder.rb +148 -33
- data/lib/datadog/di/probe_notifier_worker.rb +52 -6
- data/lib/datadog/di/probe_repository.rb +198 -0
- data/lib/datadog/di/remote.rb +5 -6
- data/lib/datadog/di/serializer.rb +127 -9
- data/lib/datadog/di/transport/http.rb +12 -3
- data/lib/datadog/di/transport/input.rb +46 -8
- data/lib/datadog/di.rb +81 -0
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/open_feature/configuration.rb +2 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +1 -1
- 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/remote.rb +1 -1
- data/lib/datadog/open_feature/transport.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +2 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +2 -3
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +14 -1
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/component.rb +31 -1
- data/lib/datadog/profiling/http_transport.rb +5 -6
- data/lib/datadog/profiling/load_native_extension.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +15 -12
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +2 -2
- data/lib/datadog/profiling/tasks/setup.rb +2 -2
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/component.rb +11 -0
- data/lib/datadog/tracing/configuration/settings.rb +2 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +20 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
- 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/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/configurable.rb +18 -3
- data/lib/datadog/tracing/contrib/dalli/integration.rb +4 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +7 -7
- data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
- data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -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/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +1 -0
- data/lib/datadog/tracing/distributed/datadog.rb +4 -2
- data/lib/datadog/tracing/event.rb +1 -1
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/remote.rb +1 -1
- data/lib/datadog/tracing/sampling/ext.rb +2 -0
- data/lib/datadog/tracing/sampling/priority_sampler.rb +13 -0
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/sync_writer.rb +0 -1
- data/lib/datadog/tracing/trace_operation.rb +50 -6
- data/lib/datadog/tracing/tracer.rb +25 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
- data/lib/datadog/tracing/writer.rb +0 -1
- data/lib/datadog/version.rb +1 -1
- metadata +15 -8
- data/lib/datadog/tracing/workers/trace_writer.rb +0 -204
|
@@ -40,7 +40,8 @@ append_cflags '-Werror' if ENV['DATADOG_GEM_CI'] == 'true'
|
|
|
40
40
|
# * by upstream Ruby -- search for gnu99 in the codebase
|
|
41
41
|
# * by msgpack, another datadog gem dependency
|
|
42
42
|
# (https://github.com/msgpack/msgpack-ruby/blob/18ce08f6d612fe973843c366ac9a0b74c4e50599/ext/msgpack/extconf.rb#L8)
|
|
43
|
-
|
|
43
|
+
# @ivoanjo: We could probably start using C11/gnu11 for non macOS-too but it's somewhat hard to validate so I chickened out for now
|
|
44
|
+
append_cflags RUBY_PLATFORM.include?('darwin') ? '-std=gnu11' : '-std=gnu99'
|
|
44
45
|
|
|
45
46
|
# Allow defining variables at any point in a function
|
|
46
47
|
append_cflags '-Wno-declaration-after-statement'
|
|
@@ -74,29 +75,13 @@ if ENV['DDTRACE_DEBUG'] == 'true'
|
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
# If we got here, libdatadog is available and loaded
|
|
77
|
-
ENV['PKG_CONFIG_PATH'] = "#{ENV["PKG_CONFIG_PATH"]}:#{Libdatadog.pkgconfig_folder}"
|
|
78
|
-
Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV["PKG_CONFIG_PATH"].inspect}\n")
|
|
79
78
|
$stderr.puts("Using libdatadog #{Libdatadog::VERSION} from #{Libdatadog.pkgconfig_folder}")
|
|
80
79
|
|
|
81
|
-
unless
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if Datadog::LibdatadogExtconfHelpers.pkg_config_missing?
|
|
85
|
-
skip_building_extension!('the `pkg-config` system tool is missing')
|
|
86
|
-
else
|
|
87
|
-
skip_building_extension!('there was a problem in setting up the `libdatadog` dependency')
|
|
88
|
-
end
|
|
80
|
+
unless Datadog::LibdatadogExtconfHelpers.configure_libdatadog(extconf_folder: __dir__)
|
|
81
|
+
skip_building_extension!('there was a problem in setting up the `libdatadog` dependency')
|
|
89
82
|
end
|
|
90
83
|
|
|
91
|
-
|
|
92
|
-
# The extremely excessive escaping around ORIGIN below seems to be correct and was determined after a lot of
|
|
93
|
-
# experimentation. We need to get these special characters across a lot of tools untouched...
|
|
94
|
-
extra_relative_rpaths = [
|
|
95
|
-
Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_native_lib_folder(current_folder: __dir__),
|
|
96
|
-
*Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_ruby_extensions_folders,
|
|
97
|
-
]
|
|
98
|
-
extra_relative_rpaths.each { |folder| $LDFLAGS += " -Wl,-rpath,$$$\\\\{ORIGIN\\}/#{folder.to_str}" }
|
|
99
|
-
Logging.message("[datadog] After pkg-config $LDFLAGS were set to: #{$LDFLAGS.inspect}\n")
|
|
84
|
+
Datadog::LibdatadogExtconfHelpers.add_libdatadog_version_define
|
|
100
85
|
|
|
101
86
|
# Tag the native extension library with the Ruby version and Ruby platform.
|
|
102
87
|
# This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
|
data/ext/libdatadog_api/init.c
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
2
|
|
|
3
3
|
#include "datadog_ruby_common.h"
|
|
4
|
+
|
|
4
5
|
#include "crashtracker.h"
|
|
5
|
-
#include "process_discovery.h"
|
|
6
|
-
#include "library_config.h"
|
|
7
6
|
#include "feature_flags.h"
|
|
7
|
+
#include "library_config.h"
|
|
8
|
+
#include "process_discovery.h"
|
|
8
9
|
|
|
9
10
|
void ddsketch_init(VALUE core_module);
|
|
11
|
+
void di_init(VALUE datadog_module);
|
|
10
12
|
|
|
11
13
|
void DDTRACE_EXPORT Init_libdatadog_api(void) {
|
|
12
14
|
VALUE datadog_module = rb_define_module("Datadog");
|
|
@@ -21,4 +23,5 @@ void DDTRACE_EXPORT Init_libdatadog_api(void) {
|
|
|
21
23
|
library_config_init(core_module);
|
|
22
24
|
ddsketch_init(core_module);
|
|
23
25
|
feature_flags_init(core_module);
|
|
26
|
+
di_init(datadog_module);
|
|
24
27
|
}
|
|
@@ -10,7 +10,7 @@ module Datadog
|
|
|
10
10
|
module LibdatadogExtconfHelpers
|
|
11
11
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
|
12
12
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
|
13
|
-
LIBDATADOG_VERSION = '~>
|
|
13
|
+
LIBDATADOG_VERSION = '~> 30.0.0.1.0'
|
|
14
14
|
|
|
15
15
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
|
16
16
|
# libdatadog are moved after the extension gets compiled.
|
|
@@ -23,9 +23,9 @@ module Datadog
|
|
|
23
23
|
# Linux: e.g. `readelf -d datadog_profiling_native_extension.2.7.3_x86_64-linux.so`.
|
|
24
24
|
#
|
|
25
25
|
# In older versions of the datadog gem, we only set as runpath an absolute path to libdatadog.
|
|
26
|
-
# (This gets set automatically by the call
|
|
27
|
-
#
|
|
28
|
-
#
|
|
26
|
+
# (This gets set automatically by the call to `configure_libdatadog` in `extconf.rb`).
|
|
27
|
+
# This worked fine as long as libdatadog was **NOT** moved from the folder it was present at
|
|
28
|
+
# datadog gem installation/linking time.
|
|
29
29
|
#
|
|
30
30
|
# Unfortunately, environments such as Heroku and AWS Elastic Beanstalk move gems around in the filesystem after
|
|
31
31
|
# installation. Thus, the profiling native extension could not be loaded in these environments
|
|
@@ -47,12 +47,12 @@ module Datadog
|
|
|
47
47
|
# we could setup when doing a `require`.
|
|
48
48
|
#
|
|
49
49
|
def self.libdatadog_folder_relative_to_native_lib_folder(
|
|
50
|
-
|
|
50
|
+
extconf_folder:,
|
|
51
51
|
libdatadog_pkgconfig_folder: Libdatadog.pkgconfig_folder
|
|
52
52
|
)
|
|
53
53
|
return unless libdatadog_pkgconfig_folder
|
|
54
54
|
|
|
55
|
-
native_lib_folder = "#{
|
|
55
|
+
native_lib_folder = "#{extconf_folder}/../../lib/"
|
|
56
56
|
libdatadog_lib_folder = "#{libdatadog_pkgconfig_folder}/../"
|
|
57
57
|
|
|
58
58
|
Pathname.new(libdatadog_lib_folder).relative_path_from(Pathname.new(native_lib_folder)).to_s
|
|
@@ -104,13 +104,51 @@ module Datadog
|
|
|
104
104
|
end
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
# Directly configures mkmf to link against libdatadog by setting $INCFLAGS, $LDFLAGS, and $libs.
|
|
108
|
+
#
|
|
109
|
+
# This replaces the previous use of mkmf's `pkg_config("datadog_profiling_with_rpath")`, removing the need for
|
|
110
|
+
# the pkg-config system tool to be installed.
|
|
111
|
+
#
|
|
112
|
+
# The extconf_folder argument should be the __dir__ of the calling extconf.rb, used to compute relative rpaths.
|
|
113
|
+
# The logger argument is the mkmf Logging module, dependency-injected to make testing easier.
|
|
114
|
+
# rubocop:disable Style/GlobalVars
|
|
115
|
+
def self.configure_libdatadog(
|
|
116
|
+
extconf_folder:,
|
|
117
|
+
libdatadog_pkgconfig_folder: Libdatadog.pkgconfig_folder,
|
|
118
|
+
gem_dir: Gem.dir,
|
|
119
|
+
logger: Logging
|
|
120
|
+
)
|
|
121
|
+
return unless libdatadog_pkgconfig_folder
|
|
122
|
+
|
|
123
|
+
# The lib and include folders are at a fixed relative path from pkgconfig_folder
|
|
124
|
+
libdir = "#{libdatadog_pkgconfig_folder}/../../lib"
|
|
125
|
+
includedir = "#{libdatadog_pkgconfig_folder}/../../include"
|
|
111
126
|
|
|
112
|
-
|
|
127
|
+
# Set mkmf global variables
|
|
128
|
+
$INCFLAGS << " -I#{includedir}"
|
|
129
|
+
$LDFLAGS << " -L#{libdir} -Wl,-rpath,#{libdir}"
|
|
130
|
+
$libs << " -ldatadog_profiling"
|
|
131
|
+
|
|
132
|
+
# Add extra relative rpaths using $ORIGIN to handle environments where gems are moved after installation.
|
|
133
|
+
# The excessive escaping is needed to get these special characters through Make and the shell untouched.
|
|
134
|
+
extra_relative_rpaths = [
|
|
135
|
+
libdatadog_folder_relative_to_native_lib_folder(
|
|
136
|
+
extconf_folder: extconf_folder,
|
|
137
|
+
libdatadog_pkgconfig_folder: libdatadog_pkgconfig_folder,
|
|
138
|
+
),
|
|
139
|
+
*libdatadog_folder_relative_to_ruby_extensions_folders(
|
|
140
|
+
gem_dir: gem_dir,
|
|
141
|
+
libdatadog_pkgconfig_folder: libdatadog_pkgconfig_folder,
|
|
142
|
+
),
|
|
143
|
+
]
|
|
144
|
+
extra_relative_rpaths.each { |folder| $LDFLAGS << " -Wl,-rpath,$$$\\\\{ORIGIN\\}/#{folder}" }
|
|
145
|
+
|
|
146
|
+
logger.message("linking with libdatadog (include=#{includedir}, lib=#{libdir})\n")
|
|
147
|
+
logger.message("[datadog] $LDFLAGS were set to: #{$LDFLAGS.inspect}\n")
|
|
148
|
+
|
|
149
|
+
true
|
|
113
150
|
end
|
|
151
|
+
# rubocop:enable Style/GlobalVars
|
|
114
152
|
|
|
115
153
|
def self.try_loading_libdatadog
|
|
116
154
|
gem 'libdatadog', LIBDATADOG_VERSION
|
|
@@ -124,6 +162,14 @@ module Datadog
|
|
|
124
162
|
end
|
|
125
163
|
end
|
|
126
164
|
|
|
165
|
+
# Adds a C preprocessor define with the libdatadog version used at compile time.
|
|
166
|
+
# This allows runtime verification that the loaded libdatadog matches what was compiled against.
|
|
167
|
+
# rubocop:disable Style/GlobalVars
|
|
168
|
+
def self.add_libdatadog_version_define
|
|
169
|
+
$defs << %(-DEXPECTED_LIBDATADOG_VERSION=\\"#{Libdatadog::VERSION}\\")
|
|
170
|
+
end
|
|
171
|
+
# rubocop:enable Style/GlobalVars
|
|
172
|
+
|
|
127
173
|
# Note: This helper is currently only used in the `libdatadog_api/extconf.rb` BUT still lives here to enable testing.
|
|
128
174
|
def self.load_libdatadog_or_get_issue
|
|
129
175
|
try_loading_libdatadog do |exception|
|
|
@@ -7,6 +7,8 @@ require_relative 'evaluation/result'
|
|
|
7
7
|
require_relative 'evaluation/no_op_result'
|
|
8
8
|
require_relative 'evaluation/message'
|
|
9
9
|
require_relative 'evaluation/tool_call'
|
|
10
|
+
require_relative 'evaluation/content_part'
|
|
11
|
+
require_relative 'evaluation/content_builder'
|
|
10
12
|
require_relative 'ext'
|
|
11
13
|
|
|
12
14
|
module Datadog
|
|
@@ -17,6 +17,9 @@ module Datadog
|
|
|
17
17
|
base.class_eval do
|
|
18
18
|
# AI Guard specific configurations.
|
|
19
19
|
# @public_api
|
|
20
|
+
#
|
|
21
|
+
# Steep does not update `self` for this `class_eval` block.
|
|
22
|
+
# @type self: Datadog::Core::Configuration::Base::_DslContext
|
|
20
23
|
settings :ai_guard do
|
|
21
24
|
# Enable AI Guard.
|
|
22
25
|
#
|
|
@@ -14,13 +14,51 @@ module Datadog
|
|
|
14
14
|
AIGuard.assistant(id: tool_call_id, tool_name: tool_call.name, arguments: tool_call.arguments.to_s)
|
|
15
15
|
end
|
|
16
16
|
elsif message.tool_result?
|
|
17
|
-
|
|
17
|
+
build_ai_guard_tool(message)
|
|
18
18
|
else
|
|
19
|
-
|
|
19
|
+
build_ai_guard_message(message)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
AIGuard.evaluate(*ai_guard_messages
|
|
23
|
+
AIGuard.evaluate(*ai_guard_messages)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def build_ai_guard_message(message)
|
|
29
|
+
content = message.content
|
|
30
|
+
|
|
31
|
+
case content
|
|
32
|
+
when ::RubyLLM::Content
|
|
33
|
+
AIGuard.message(role: message.role) do |m|
|
|
34
|
+
m.text(content.text.to_s) if content.text
|
|
35
|
+
|
|
36
|
+
# Calling attachment.for_llm triggers lazy loading of file contents.
|
|
37
|
+
# The result is memoized, so providers won't re-read.
|
|
38
|
+
content.attachments.each do |attachment|
|
|
39
|
+
case attachment.type
|
|
40
|
+
when :image
|
|
41
|
+
m.image_url(attachment.for_llm)
|
|
42
|
+
when :text
|
|
43
|
+
m.text(attachment.for_llm)
|
|
44
|
+
end
|
|
45
|
+
# Skip :pdf, :audio, :video, :unknown — not supported by AIGuard
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
AIGuard.message(role: message.role, content: content)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def build_ai_guard_tool(message)
|
|
54
|
+
content = message.content
|
|
55
|
+
# Tools can return Content or Content::Raw objects (e.g. with attachments),
|
|
56
|
+
# but AIGuard.tool expects a String. Extract text when content is a Content object.
|
|
57
|
+
case content
|
|
58
|
+
when ::RubyLLM::Content
|
|
59
|
+
content = content.text.to_s
|
|
60
|
+
end
|
|
61
|
+
AIGuard.tool(tool_call_id: message.tool_call_id, content: content)
|
|
24
62
|
end
|
|
25
63
|
end
|
|
26
64
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Builder for collecting content parts inside a message block.
|
|
7
|
+
#
|
|
8
|
+
# Used via the block form of {Datadog::AIGuard.message}:
|
|
9
|
+
#
|
|
10
|
+
# Datadog::AIGuard.message(role: :user) do |m|
|
|
11
|
+
# m.text("What's in this image?")
|
|
12
|
+
# m.image_url("https://example.com/img.png")
|
|
13
|
+
# end
|
|
14
|
+
class ContentBuilder
|
|
15
|
+
attr_reader :parts
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
@parts = []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def text(text)
|
|
22
|
+
@parts << ContentPart::Text.new(text)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def image_url(url)
|
|
26
|
+
@parts << ContentPart::ImageURL.new(url)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Namespace for content part types used in multi-modal messages.
|
|
7
|
+
module ContentPart
|
|
8
|
+
# A text content part.
|
|
9
|
+
class Text
|
|
10
|
+
attr_reader :text
|
|
11
|
+
|
|
12
|
+
def initialize(text)
|
|
13
|
+
@text = text
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def type
|
|
17
|
+
:text
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# An image URL content part. Accepts an absolute URL or a base64 data URI.
|
|
22
|
+
class ImageURL
|
|
23
|
+
attr_reader :url
|
|
24
|
+
|
|
25
|
+
def initialize(url)
|
|
26
|
+
@url = url
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def type
|
|
30
|
+
:image_url
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -5,12 +5,14 @@ module Datadog
|
|
|
5
5
|
module Evaluation
|
|
6
6
|
# Class for emulating AI Guard evaluation result when AI Guard is disabled.
|
|
7
7
|
class NoOpResult
|
|
8
|
-
attr_reader :action, :reason, :tags
|
|
8
|
+
attr_reader :action, :reason, :tags, :sds_findings, :tag_probabilities
|
|
9
9
|
|
|
10
10
|
def initialize
|
|
11
11
|
@action = Result::ALLOW_ACTION
|
|
12
12
|
@reason = "AI Guard is disabled"
|
|
13
13
|
@tags = []
|
|
14
|
+
@sds_findings = []
|
|
15
|
+
@tag_probabilities = {}
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def allow?
|
|
@@ -44,15 +44,7 @@ module Datadog
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def serialize_messages(messages)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
messages.each do |message|
|
|
50
|
-
serialized_messages << serialize_message(message)
|
|
51
|
-
|
|
52
|
-
break if serialized_messages.count == Datadog.configuration.ai_guard.max_messages_length
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
serialized_messages
|
|
47
|
+
messages.map { |message| serialize_message(message) }
|
|
56
48
|
end
|
|
57
49
|
|
|
58
50
|
def serialize_message(message)
|
|
@@ -69,12 +61,25 @@ module Datadog
|
|
|
69
61
|
}
|
|
70
62
|
]
|
|
71
63
|
}
|
|
64
|
+
elsif message.content.is_a?(::Array)
|
|
65
|
+
{role: message.role, content: serialize_content_parts(message.content)}
|
|
72
66
|
elsif message.tool_call_id
|
|
73
67
|
{role: message.role, tool_call_id: message.tool_call_id, content: message.content}
|
|
74
68
|
else
|
|
75
69
|
{role: message.role, content: message.content}
|
|
76
70
|
end
|
|
77
71
|
end
|
|
72
|
+
|
|
73
|
+
def serialize_content_parts(parts)
|
|
74
|
+
parts.map do |part|
|
|
75
|
+
case part
|
|
76
|
+
when ContentPart::Text
|
|
77
|
+
{type: "text", text: part.text}
|
|
78
|
+
when ContentPart::ImageURL
|
|
79
|
+
{type: "image_url", image_url: {url: part.url}}
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
78
83
|
end
|
|
79
84
|
end
|
|
80
85
|
end
|
|
@@ -9,7 +9,7 @@ module Datadog
|
|
|
9
9
|
DENY_ACTION = "DENY"
|
|
10
10
|
ABORT_ACTION = "ABORT"
|
|
11
11
|
|
|
12
|
-
attr_reader :action, :reason, :tags
|
|
12
|
+
attr_reader :action, :reason, :tags, :sds_findings, :tag_probabilities
|
|
13
13
|
|
|
14
14
|
def initialize(raw_response)
|
|
15
15
|
attributes = raw_response.fetch("data").fetch("attributes")
|
|
@@ -17,7 +17,9 @@ module Datadog
|
|
|
17
17
|
@action = attributes.fetch("action")
|
|
18
18
|
@reason = attributes.fetch("reason")
|
|
19
19
|
@tags = attributes.fetch("tags")
|
|
20
|
+
@tag_probabilities = attributes.fetch("tag_probs")
|
|
20
21
|
@is_blocking_enabled = attributes.fetch("is_blocking_enabled")
|
|
22
|
+
@sds_findings = attributes.fetch("sds_findings", [])
|
|
21
23
|
rescue KeyError => e
|
|
22
24
|
raise AIGuardClientError, "Missing key: \"#{e.key}\""
|
|
23
25
|
end
|
|
@@ -6,10 +6,16 @@ module Datadog
|
|
|
6
6
|
# and creating `ai_guard` span with required tags
|
|
7
7
|
module Evaluation
|
|
8
8
|
class << self
|
|
9
|
-
def perform(messages, allow_raise:
|
|
9
|
+
def perform(messages, allow_raise: true)
|
|
10
10
|
raise ArgumentError, "Messages must not be empty" if messages&.empty?
|
|
11
11
|
|
|
12
12
|
Tracing.trace(Ext::SPAN_NAME) do |span, trace|
|
|
13
|
+
trace.keep!
|
|
14
|
+
trace.set_tag(
|
|
15
|
+
Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
|
16
|
+
Tracing::Sampling::Ext::Decision::AI_GUARD
|
|
17
|
+
)
|
|
18
|
+
|
|
13
19
|
if (last_message = messages.last)
|
|
14
20
|
if last_message.tool_call
|
|
15
21
|
span.set_tag(Ext::TARGET_TAG, "tool")
|
|
@@ -34,8 +40,10 @@ module Datadog
|
|
|
34
40
|
span.set_metastruct_tag(
|
|
35
41
|
Ext::METASTRUCT_TAG,
|
|
36
42
|
{
|
|
37
|
-
messages: truncate_content(request.serialized_messages),
|
|
38
|
-
attack_categories: result.tags
|
|
43
|
+
messages: truncate_content(truncate_messages(request.serialized_messages)),
|
|
44
|
+
attack_categories: result.tags,
|
|
45
|
+
sds: result.sds_findings,
|
|
46
|
+
tag_probs: result.tag_probabilities
|
|
39
47
|
}
|
|
40
48
|
)
|
|
41
49
|
|
|
@@ -56,14 +64,35 @@ module Datadog
|
|
|
56
64
|
|
|
57
65
|
private
|
|
58
66
|
|
|
67
|
+
def truncate_messages(serialized_messages)
|
|
68
|
+
max_length = Datadog.configuration.ai_guard.max_messages_length
|
|
69
|
+
serialized_messages.first(max_length)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Truncates content in serialized messages to stay within the configured byte limit.
|
|
73
|
+
# For multi-modal messages, only text parts are truncated; image URLs are left intact.
|
|
59
74
|
def truncate_content(serialized_messages)
|
|
75
|
+
max_bytes = Datadog.configuration.ai_guard.max_content_size_bytes
|
|
76
|
+
|
|
60
77
|
serialized_messages.map do |message| # steep:ignore
|
|
61
78
|
next message unless message[:content]
|
|
62
79
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
if message[:content].is_a?(::Array)
|
|
81
|
+
serialized_content = message[:content].map do |part|
|
|
82
|
+
if part[:text]
|
|
83
|
+
{**part, text: part[:text].to_s.byteslice(0, max_bytes)}
|
|
84
|
+
else
|
|
85
|
+
part
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
{**message, content: serialized_content}
|
|
90
|
+
else
|
|
91
|
+
{
|
|
92
|
+
**message,
|
|
93
|
+
content: message[:content].byteslice(0, max_bytes)
|
|
94
|
+
}
|
|
95
|
+
end
|
|
67
96
|
end
|
|
68
97
|
end
|
|
69
98
|
end
|
data/lib/datadog/ai_guard.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Datadog
|
|
|
10
10
|
module AIGuard
|
|
11
11
|
Core::Configuration::Settings.extend(Configuration::Settings)
|
|
12
12
|
|
|
13
|
-
# This error is raised when
|
|
13
|
+
# This error is raised when `allow_raise` is set to true (the default) in Evaluation.perform
|
|
14
14
|
# and AI Guard considers the messages not safe. Intended to be rescued by the user.
|
|
15
15
|
#
|
|
16
16
|
# WARNING: This name must not change, since front-end is using it.
|
|
@@ -68,13 +68,14 @@ module Datadog
|
|
|
68
68
|
# One or more message objects to be evaluated.
|
|
69
69
|
# @param allow_raise [Boolean]
|
|
70
70
|
# Whether this method may raise an exception when evaluation result is not ALLOW.
|
|
71
|
+
# Defaults to true.
|
|
71
72
|
#
|
|
72
73
|
# @return [Datadog::AIGuard::Evaluation::Result]
|
|
73
74
|
# The result of AI Guard evaluation.
|
|
74
75
|
# @raise [Datadog::AIGuard::AIGuardAbortError]
|
|
75
76
|
# If the evaluation results in DENY or ABORT action and `allow_raise` is set to true
|
|
76
77
|
# @public_api
|
|
77
|
-
def evaluate(*messages, allow_raise:
|
|
78
|
+
def evaluate(*messages, allow_raise: true)
|
|
78
79
|
if enabled?
|
|
79
80
|
Evaluation.perform(messages, allow_raise: allow_raise)
|
|
80
81
|
else
|
|
@@ -84,25 +85,42 @@ module Datadog
|
|
|
84
85
|
|
|
85
86
|
# Builds a generic evaluation message.
|
|
86
87
|
#
|
|
87
|
-
#
|
|
88
|
+
# Accepts either a string content or a block for multi-modal content parts:
|
|
88
89
|
#
|
|
89
90
|
# ```
|
|
91
|
+
# # String content:
|
|
90
92
|
# Datadog::AIGuard.message(role: :user, content: "Hello, assistant")
|
|
93
|
+
#
|
|
94
|
+
# # Multi-modal content with block:
|
|
95
|
+
# Datadog::AIGuard.message(role: :user) do |m|
|
|
96
|
+
# m.text("What's in this image?")
|
|
97
|
+
# m.image_url("https://example.com/img.png")
|
|
98
|
+
# end
|
|
91
99
|
# ```
|
|
92
100
|
#
|
|
93
101
|
# @param role [Symbol]
|
|
94
102
|
# The role associated with the message.
|
|
95
103
|
# Must be one of `:assistant`, `:tool`, `:system`, `:developer`, or `:user`.
|
|
96
|
-
# @param content [String]
|
|
97
|
-
# The textual content of the message.
|
|
104
|
+
# @param content [String, nil]
|
|
105
|
+
# The textual content of the message. Cannot be combined with a block.
|
|
106
|
+
# @yield [builder] A block for building multi-modal content parts.
|
|
107
|
+
# @yieldparam builder [Datadog::AIGuard::Evaluation::ContentBuilder]
|
|
98
108
|
#
|
|
99
109
|
# @return [Datadog::AIGuard::Evaluation::Message]
|
|
100
110
|
# A new message instance with the given role and content.
|
|
101
111
|
# @raise [ArgumentError]
|
|
102
|
-
# If an invalid role is provided.
|
|
112
|
+
# If both content and a block are provided, or if an invalid role is provided.
|
|
103
113
|
# @public_api
|
|
104
|
-
def message(role:, content:)
|
|
105
|
-
|
|
114
|
+
def message(role:, content: nil)
|
|
115
|
+
if block_given?
|
|
116
|
+
raise ArgumentError, "Cannot pass both content and a block" if content
|
|
117
|
+
|
|
118
|
+
builder = Evaluation::ContentBuilder.new
|
|
119
|
+
yield builder
|
|
120
|
+
Evaluation::Message.new(role: role, content: builder.parts)
|
|
121
|
+
else
|
|
122
|
+
Evaluation::Message.new(role: role, content: content)
|
|
123
|
+
end
|
|
106
124
|
end
|
|
107
125
|
|
|
108
126
|
# Builds an assistant message representing a tool call initiated by the model.
|
|
@@ -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
|
|
10
|
+
" #{e.class}: #{e}"
|
|
11
11
|
)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -45,10 +45,15 @@ module Datadog
|
|
|
45
45
|
settings.appsec.instrument(:devise) unless devise_integration.patcher.patched?
|
|
46
46
|
|
|
47
47
|
security_engine = SecurityEngine::Engine.new(appsec_settings: settings.appsec, telemetry: telemetry)
|
|
48
|
-
new(security_engine: security_engine
|
|
49
|
-
rescue
|
|
50
|
-
Datadog.logger.warn(
|
|
51
|
-
|
|
48
|
+
new(security_engine: security_engine)
|
|
49
|
+
rescue => e
|
|
50
|
+
Datadog.logger.warn("AppSec is disabled: #{e.class}: #{e}; there may be additional logged errors above")
|
|
51
|
+
|
|
52
|
+
# Not reporting to telemetry here because some of the rescued exceptions
|
|
53
|
+
# have already been reported by the code that raised them
|
|
54
|
+
# (e.g. SecurityEngine::Engine.new reports WAF init failures).
|
|
55
|
+
# TODO: reconsider whether telemetry reporting belongs here
|
|
56
|
+
# (single catch-all) or in the downstream code (as it is now).
|
|
52
57
|
nil
|
|
53
58
|
end
|
|
54
59
|
|
|
@@ -70,11 +75,10 @@ module Datadog
|
|
|
70
75
|
end
|
|
71
76
|
end
|
|
72
77
|
|
|
73
|
-
attr_reader :security_engine
|
|
78
|
+
attr_reader :security_engine
|
|
74
79
|
|
|
75
|
-
def initialize(security_engine
|
|
80
|
+
def initialize(security_engine:)
|
|
76
81
|
@security_engine = security_engine
|
|
77
|
-
@telemetry = telemetry
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
def reconfigure!
|
|
@@ -61,6 +61,7 @@ module Datadog
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
::ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(instrumentation_module)
|
|
64
|
+
Patcher.instance_variable_set(:@patched, true)
|
|
64
65
|
end
|
|
65
66
|
|
|
66
67
|
def patch_mysql2_adapter
|
|
@@ -73,6 +74,7 @@ module Datadog
|
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
::ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend(instrumentation_module)
|
|
77
|
+
Patcher.instance_variable_set(:@patched, true)
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
def patch_postgresql_adapter
|
|
@@ -93,6 +95,7 @@ module Datadog
|
|
|
93
95
|
end
|
|
94
96
|
|
|
95
97
|
::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(instrumentation_module)
|
|
98
|
+
Patcher.instance_variable_set(:@patched, true)
|
|
96
99
|
end
|
|
97
100
|
end
|
|
98
101
|
end
|
|
@@ -98,7 +98,7 @@ module Datadog
|
|
|
98
98
|
|
|
99
99
|
def request_url(data)
|
|
100
100
|
klass = (data[:scheme] == 'https') ? URI::HTTPS : URI::HTTP
|
|
101
|
-
klass.build(host: data[:host], path: data[:path], query: data[:query]).to_s
|
|
101
|
+
klass.build(host: data[:host], port: data[:port], path: data[:path], query: data[:query]).to_s
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
def normalize_headers(headers)
|
|
@@ -22,7 +22,7 @@ module Datadog
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def watch_multiplex(gateway = Instrumentation.gateway)
|
|
25
|
-
gateway.watch('graphql.multiplex'
|
|
25
|
+
gateway.watch('graphql.multiplex') do |stack, gateway_multiplex|
|
|
26
26
|
context = AppSec::Context.active
|
|
27
27
|
|
|
28
28
|
if context
|
|
@@ -25,7 +25,7 @@ module Datadog
|
|
|
25
25
|
def query
|
|
26
26
|
::Rack::Utils.parse_query(request.query_string)
|
|
27
27
|
rescue => e
|
|
28
|
-
Datadog.logger.debug { "AppSec: Failed to parse request query string: #{e.class}: #{e
|
|
28
|
+
Datadog.logger.debug { "AppSec: Failed to parse request query string: #{e.class}: #{e}" }
|
|
29
29
|
AppSec.telemetry.report(e, description: 'AppSec: Failed to parse request query string')
|
|
30
30
|
|
|
31
31
|
{}
|