datadog 2.20.0 → 2.26.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 +212 -1
- data/README.md +0 -1
- data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +93 -23
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +21 -5
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +9 -4
- data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +1 -0
- 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/ext/libdatadog_api/datadog_ruby_common.h +1 -1
- data/ext/libdatadog_api/ddsketch.c +106 -0
- data/ext/libdatadog_api/feature_flags.c +554 -0
- data/ext/libdatadog_api/feature_flags.h +5 -0
- data/ext/libdatadog_api/init.c +5 -0
- data/ext/libdatadog_api/library_config.c +34 -25
- data/ext/libdatadog_api/process_discovery.c +24 -18
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- 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/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +26 -5
- data/lib/datadog/appsec/api_security/sampler.rb +7 -4
- data/lib/datadog/appsec/assets/blocked.html +8 -0
- data/lib/datadog/appsec/assets/blocked.json +1 -1
- data/lib/datadog/appsec/assets/blocked.text +3 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
- data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
- data/lib/datadog/appsec/assets.rb +1 -1
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/compressed_json.rb +1 -1
- data/lib/datadog/appsec/configuration/settings.rb +9 -0
- data/lib/datadog/appsec/context.rb +2 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
- data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
- data/lib/datadog/appsec/event.rb +12 -14
- data/lib/datadog/appsec/metrics/collector.rb +19 -3
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
- data/lib/datadog/appsec/remote.rb +34 -25
- data/lib/datadog/appsec/response.rb +18 -4
- data/lib/datadog/appsec/security_engine/engine.rb +3 -3
- data/lib/datadog/appsec/security_engine/result.rb +29 -9
- data/lib/datadog/appsec/security_engine/runner.rb +19 -9
- data/lib/datadog/appsec/security_event.rb +5 -7
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -4
- data/lib/datadog/core/configuration/components.rb +59 -11
- data/lib/datadog/core/configuration/config_helper.rb +100 -0
- data/lib/datadog/core/configuration/deprecations.rb +36 -0
- data/lib/datadog/core/configuration/ext.rb +0 -1
- data/lib/datadog/core/configuration/option.rb +38 -43
- data/lib/datadog/core/configuration/option_definition.rb +4 -11
- data/lib/datadog/core/configuration/options.rb +9 -10
- data/lib/datadog/core/configuration/settings.rb +38 -9
- data/lib/datadog/core/configuration/stable_config.rb +10 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +373 -0
- data/lib/datadog/core/configuration.rb +2 -2
- data/lib/datadog/core/ddsketch.rb +19 -0
- data/lib/datadog/core/deprecations.rb +2 -2
- 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 +7 -2
- data/lib/datadog/core/environment/git.rb +2 -2
- data/lib/datadog/core/environment/process.rb +87 -0
- data/lib/datadog/core/environment/variable_helpers.rb +3 -3
- data/lib/datadog/core/environment/yjit.rb +2 -1
- data/lib/datadog/core/error.rb +6 -6
- data/lib/datadog/core/feature_flags.rb +61 -0
- data/lib/datadog/core/metrics/client.rb +2 -2
- data/lib/datadog/core/pin.rb +8 -8
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +2 -4
- data/lib/datadog/core/process_discovery.rb +48 -23
- data/lib/datadog/core/rate_limiter.rb +9 -1
- data/lib/datadog/core/remote/client/capabilities.rb +7 -0
- data/lib/datadog/core/remote/client.rb +14 -6
- data/lib/datadog/core/remote/component.rb +10 -10
- 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 +4 -25
- data/lib/datadog/core/remote/transport/http/config.rb +10 -50
- data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
- data/lib/datadog/core/remote/transport/http.rb +15 -24
- data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
- data/lib/datadog/core/remote/worker.rb +25 -37
- data/lib/datadog/core/runtime/ext.rb +0 -1
- data/lib/datadog/core/runtime/metrics.rb +11 -1
- data/lib/datadog/core/semaphore.rb +1 -4
- data/lib/datadog/core/tag_builder.rb +0 -4
- data/lib/datadog/core/tag_normalizer.rb +84 -0
- data/lib/datadog/core/telemetry/component.rb +69 -15
- data/lib/datadog/core/telemetry/emitter.rb +6 -6
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +89 -51
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
- data/lib/datadog/core/telemetry/event.rb +1 -0
- data/lib/datadog/core/telemetry/logger.rb +2 -2
- data/lib/datadog/core/telemetry/logging.rb +2 -8
- 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 +3 -34
- data/lib/datadog/core/telemetry/transport/http.rb +21 -16
- data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -11
- 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 +80 -0
- data/lib/datadog/core/transport/http.rb +22 -19
- data/lib/datadog/core/transport/response.rb +15 -1
- data/lib/datadog/core/transport/transport.rb +90 -0
- data/lib/datadog/core/utils/array.rb +29 -0
- data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
- data/lib/datadog/core/utils/network.rb +22 -1
- data/lib/datadog/core/utils/only_once_successful.rb +8 -2
- 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/utils.rb +2 -0
- 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/core.rb +2 -0
- data/lib/datadog/data_streams/configuration/settings.rb +49 -0
- data/lib/datadog/data_streams/configuration.rb +11 -0
- data/lib/datadog/data_streams/ext.rb +11 -0
- data/lib/datadog/data_streams/extensions.rb +16 -0
- data/lib/datadog/data_streams/pathway_context.rb +169 -0
- data/lib/datadog/data_streams/processor.rb +509 -0
- data/lib/datadog/data_streams/transport/http/stats.rb +52 -0
- data/lib/datadog/data_streams/transport/http.rb +40 -0
- data/lib/datadog/data_streams/transport/stats.rb +46 -0
- data/lib/datadog/data_streams.rb +100 -0
- data/lib/datadog/di/boot.rb +7 -3
- data/lib/datadog/di/component.rb +14 -16
- data/lib/datadog/di/context.rb +70 -0
- data/lib/datadog/di/contrib/active_record.rb +30 -5
- data/lib/datadog/di/el/compiler.rb +168 -0
- data/lib/datadog/di/el/evaluator.rb +159 -0
- data/lib/datadog/di/el/expression.rb +42 -0
- data/lib/datadog/di/el.rb +5 -0
- data/lib/datadog/di/error.rb +34 -0
- data/lib/datadog/di/instrumenter.rb +189 -55
- data/lib/datadog/di/logger.rb +2 -2
- data/lib/datadog/di/probe.rb +55 -15
- data/lib/datadog/di/probe_builder.rb +41 -2
- data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +1 -1
- data/lib/datadog/di/probe_manager.rb +50 -35
- data/lib/datadog/di/probe_notification_builder.rb +121 -70
- data/lib/datadog/di/probe_notifier_worker.rb +5 -5
- data/lib/datadog/di/proc_responder.rb +32 -0
- data/lib/datadog/di/remote.rb +89 -84
- data/lib/datadog/di/serializer.rb +151 -7
- data/lib/datadog/di/transport/diagnostics.rb +8 -36
- data/lib/datadog/di/transport/http/diagnostics.rb +1 -33
- data/lib/datadog/di/transport/http/input.rb +1 -33
- data/lib/datadog/di/transport/http.rb +32 -17
- data/lib/datadog/di/transport/input.rb +67 -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/component.rb +60 -0
- data/lib/datadog/open_feature/configuration.rb +27 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
- data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
- data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
- data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
- data/lib/datadog/open_feature/exposures/event.rb +60 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
- data/lib/datadog/open_feature/exposures/worker.rb +116 -0
- data/lib/datadog/open_feature/ext.rb +14 -0
- data/lib/datadog/open_feature/native_evaluator.rb +38 -0
- data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
- data/lib/datadog/open_feature/provider.rb +141 -0
- data/lib/datadog/open_feature/remote.rb +67 -0
- data/lib/datadog/open_feature/resolution_details.rb +35 -0
- data/lib/datadog/open_feature/transport.rb +70 -0
- data/lib/datadog/open_feature.rb +19 -0
- data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
- data/lib/datadog/opentelemetry/metrics.rb +117 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +26 -2
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +35 -0
- data/lib/datadog/opentelemetry.rb +3 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +41 -7
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +6 -5
- data/lib/datadog/profiling/component.rb +12 -11
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
- data/lib/datadog/profiling/ext.rb +2 -1
- data/lib/datadog/profiling/http_transport.rb +5 -2
- data/lib/datadog/profiling/profiler.rb +4 -0
- data/lib/datadog/profiling/tag_builder.rb +36 -3
- data/lib/datadog/profiling/tasks/exec.rb +2 -2
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/tracing/component.rb +6 -17
- data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
- data/lib/datadog/tracing/configuration/ext.rb +9 -3
- data/lib/datadog/tracing/configuration/settings.rb +89 -10
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/component.rb +2 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/extensions.rb +10 -2
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +84 -43
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
- data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +7 -1
- data/lib/datadog/tracing/contrib/rails/ext.rb +2 -1
- data/lib/datadog/tracing/contrib/rails/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +9 -1
- data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop.rb +41 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -2
- data/lib/datadog/tracing/metadata/ext.rb +9 -1
- 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/client.rb +12 -26
- 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/trace_formatter.rb +11 -0
- data/lib/datadog/tracing/transport/traces.rb +9 -71
- 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 +3 -0
- metadata +110 -24
- data/ext/libdatadog_api/macos_development.md +0 -26
- data/lib/datadog/core/remote/transport/http/api.rb +0 -53
- data/lib/datadog/core/remote/transport/http/client.rb +0 -49
- data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
- data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
- data/lib/datadog/core/transport/http/api/spec.rb +0 -36
- data/lib/datadog/di/transport/http/api.rb +0 -42
- data/lib/datadog/di/transport/http/client.rb +0 -47
- data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
- data/lib/datadog/tracing/transport/http/api.rb +0 -44
|
@@ -11,7 +11,7 @@ static VALUE _native_configurator_get(VALUE self);
|
|
|
11
11
|
static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
|
12
12
|
static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
|
13
13
|
|
|
14
|
-
static VALUE
|
|
14
|
+
static VALUE config_logged_result_class = Qnil;
|
|
15
15
|
|
|
16
16
|
// ddog_Configurator memory management
|
|
17
17
|
static void configurator_free(void *configurator_ptr) {
|
|
@@ -29,29 +29,29 @@ static const rb_data_type_t configurator_typed_data = {
|
|
|
29
29
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
//
|
|
33
|
-
static void
|
|
34
|
-
|
|
32
|
+
// ddog_LibraryConfigLoggedResult memory management
|
|
33
|
+
static void config_logged_result_free(void *config_logged_result_ptr) {
|
|
34
|
+
ddog_LibraryConfigLoggedResult *config_logged_result = (ddog_LibraryConfigLoggedResult *)config_logged_result_ptr;
|
|
35
35
|
|
|
36
|
-
ddog_library_config_drop(*
|
|
37
|
-
ruby_xfree(
|
|
36
|
+
ddog_library_config_drop(*config_logged_result);
|
|
37
|
+
ruby_xfree(config_logged_result_ptr);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
static const rb_data_type_t
|
|
41
|
-
.wrap_struct_name = "Datadog::Core::Configuration::
|
|
40
|
+
static const rb_data_type_t config_logged_result_typed_data = {
|
|
41
|
+
.wrap_struct_name = "Datadog::Core::Configuration::StableConfigLoggedResult",
|
|
42
42
|
.function = {
|
|
43
|
-
.dfree =
|
|
43
|
+
.dfree = config_logged_result_free,
|
|
44
44
|
.dsize = NULL,
|
|
45
45
|
},
|
|
46
46
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
void library_config_init(VALUE core_module) {
|
|
50
|
-
rb_global_variable(&
|
|
50
|
+
rb_global_variable(&config_logged_result_class);
|
|
51
51
|
VALUE configuration_module = rb_define_module_under(core_module, "Configuration");
|
|
52
52
|
VALUE stable_config_module = rb_define_module_under(configuration_module, "StableConfig");
|
|
53
53
|
VALUE configurator_class = rb_define_class_under(stable_config_module, "Configurator", rb_cObject);
|
|
54
|
-
|
|
54
|
+
config_logged_result_class = rb_define_class_under(configuration_module, "StableConfigLoggedResult", rb_cObject);
|
|
55
55
|
|
|
56
56
|
rb_define_alloc_func(configurator_class, _native_configurator_new);
|
|
57
57
|
rb_define_method(configurator_class, "get", _native_configurator_get, 0);
|
|
@@ -61,11 +61,12 @@ void library_config_init(VALUE core_module) {
|
|
|
61
61
|
rb_define_singleton_method(testing_module, "with_local_path", _native_configurator_with_local_path, 2);
|
|
62
62
|
rb_define_singleton_method(testing_module, "with_fleet_path", _native_configurator_with_fleet_path, 2);
|
|
63
63
|
|
|
64
|
-
rb_undef_alloc_func(
|
|
64
|
+
rb_undef_alloc_func(config_logged_result_class); // It cannot be created from Ruby code and only serves as an intermediate object for the Ruby GC
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
static VALUE _native_configurator_new(VALUE klass) {
|
|
68
|
-
|
|
68
|
+
// We always collect debug logs, so if DD_TRACE_DEBUG is set by stable config, we'll be able to log them.
|
|
69
|
+
ddog_Configurator *configurator = ddog_library_configurator_new(true, DDOG_CHARSLICE_C("ruby"));
|
|
69
70
|
|
|
70
71
|
ddog_library_configurator_with_detect_process_info(configurator);
|
|
71
72
|
|
|
@@ -98,10 +99,11 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
|
98
99
|
ddog_Configurator *configurator;
|
|
99
100
|
TypedData_Get_Struct(self, ddog_Configurator, &configurator_typed_data, configurator);
|
|
100
101
|
|
|
101
|
-
|
|
102
|
+
// We don't allocate memory here so if there is an error, we don't need to manage the memory
|
|
103
|
+
ddog_LibraryConfigLoggedResult before_error_result = ddog_library_configurator_get(configurator);
|
|
102
104
|
|
|
103
|
-
if (
|
|
104
|
-
ddog_Error err =
|
|
105
|
+
if (before_error_result.tag == DDOG_LIBRARY_CONFIG_LOGGED_RESULT_ERR) {
|
|
106
|
+
ddog_Error err = before_error_result.err;
|
|
105
107
|
VALUE message = get_error_details_and_drop(&err);
|
|
106
108
|
if (is_config_loaded()) {
|
|
107
109
|
log_warning(message);
|
|
@@ -111,14 +113,20 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
|
111
113
|
return rb_hash_new();
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
// Wrapping
|
|
115
|
-
// We need to allocate memory for
|
|
116
|
-
// So we cannot reference it with &config_vec
|
|
116
|
+
// Wrapping config_logged_result into a Ruby object enables the Ruby GC to manage its memory
|
|
117
|
+
// We need to allocate memory for config_logged_result because once it is out of scope, it will be freed (at the end of this function)
|
|
117
118
|
// We are doing this in case one of the ruby API raises an exception before the end of this function,
|
|
118
119
|
// so the allocated memory will still be freed
|
|
119
|
-
|
|
120
|
-
*
|
|
121
|
-
VALUE
|
|
120
|
+
ddog_LibraryConfigLoggedResult *configurator_logged_result = ruby_xcalloc(1, sizeof(ddog_LibraryConfigLoggedResult));
|
|
121
|
+
*configurator_logged_result = before_error_result;
|
|
122
|
+
VALUE config_logged_result_rb = TypedData_Wrap_Struct(config_logged_result_class, &config_logged_result_typed_data, configurator_logged_result);
|
|
123
|
+
|
|
124
|
+
VALUE logs = Qnil;
|
|
125
|
+
if (configurator_logged_result->ok.logs.length > 0) {
|
|
126
|
+
logs = rb_utf8_str_new_cstr(configurator_logged_result->ok.logs.ptr);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
ddog_Vec_LibraryConfig config_vec = configurator_logged_result->ok.value;
|
|
122
130
|
|
|
123
131
|
VALUE local_config_hash = rb_hash_new();
|
|
124
132
|
VALUE fleet_config_hash = rb_hash_new();
|
|
@@ -127,8 +135,8 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
|
127
135
|
bool fleet_config_id_set = false;
|
|
128
136
|
VALUE local_hash = rb_hash_new();
|
|
129
137
|
VALUE fleet_hash = rb_hash_new();
|
|
130
|
-
for (uintptr_t i = 0; i < config_vec
|
|
131
|
-
ddog_LibraryConfig config = config_vec
|
|
138
|
+
for (uintptr_t i = 0; i < config_vec.len; i++) {
|
|
139
|
+
ddog_LibraryConfig config = config_vec.ptr[i];
|
|
132
140
|
VALUE selected_hash;
|
|
133
141
|
if (config.source == DDOG_LIBRARY_CONFIG_SOURCE_LOCAL_STABLE_CONFIG) {
|
|
134
142
|
selected_hash = local_config_hash;
|
|
@@ -156,9 +164,10 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
|
156
164
|
rb_hash_aset(fleet_hash, ID2SYM(rb_intern("config")), fleet_config_hash);
|
|
157
165
|
|
|
158
166
|
VALUE result = rb_hash_new();
|
|
167
|
+
rb_hash_aset(result, ID2SYM(rb_intern("logs")), logs);
|
|
159
168
|
rb_hash_aset(result, ID2SYM(rb_intern("local")), local_hash);
|
|
160
169
|
rb_hash_aset(result, ID2SYM(rb_intern("fleet")), fleet_hash);
|
|
161
170
|
|
|
162
|
-
RB_GC_GUARD(
|
|
171
|
+
RB_GC_GUARD(config_logged_result_rb);
|
|
163
172
|
return result;
|
|
164
173
|
}
|
|
@@ -27,13 +27,13 @@ static const rb_data_type_t tracer_memfd_type = {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
void process_discovery_init(VALUE core_module) {
|
|
30
|
-
VALUE
|
|
31
|
-
VALUE tracer_memfd_class = rb_define_class_under(
|
|
30
|
+
VALUE process_discovery_module = rb_define_module_under(core_module, "ProcessDiscovery");
|
|
31
|
+
VALUE tracer_memfd_class = rb_define_class_under(process_discovery_module, "TracerMemfd", rb_cObject);
|
|
32
32
|
rb_undef_alloc_func(tracer_memfd_class); // Class cannot be instantiated from Ruby
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
rb_define_module_function(process_discovery_module, "_native_store_tracer_metadata", _native_store_tracer_metadata, -1);
|
|
35
|
+
rb_define_module_function(process_discovery_module, "_native_to_rb_int", _native_to_rb_int, 1);
|
|
36
|
+
rb_define_module_function(process_discovery_module, "_native_close_tracer_memfd", _native_close_tracer_memfd, 2);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
@@ -42,7 +42,6 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
|
42
42
|
rb_scan_args(argc, argv, "1:", &logger, &options);
|
|
43
43
|
if (options == Qnil) options = rb_hash_new();
|
|
44
44
|
|
|
45
|
-
VALUE schema_version = rb_hash_fetch(options, ID2SYM(rb_intern("schema_version")));
|
|
46
45
|
VALUE runtime_id = rb_hash_fetch(options, ID2SYM(rb_intern("runtime_id")));
|
|
47
46
|
VALUE tracer_language = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_language")));
|
|
48
47
|
VALUE tracer_version = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_version")));
|
|
@@ -50,8 +49,9 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
|
50
49
|
VALUE service_name = rb_hash_fetch(options, ID2SYM(rb_intern("service_name")));
|
|
51
50
|
VALUE service_env = rb_hash_fetch(options, ID2SYM(rb_intern("service_env")));
|
|
52
51
|
VALUE service_version = rb_hash_fetch(options, ID2SYM(rb_intern("service_version")));
|
|
52
|
+
VALUE process_tags = rb_hash_fetch(options, ID2SYM(rb_intern("process_tags")));
|
|
53
|
+
VALUE container_id = rb_hash_fetch(options, ID2SYM(rb_intern("container_id")));
|
|
53
54
|
|
|
54
|
-
ENFORCE_TYPE(schema_version, T_FIXNUM);
|
|
55
55
|
ENFORCE_TYPE(runtime_id, T_STRING);
|
|
56
56
|
ENFORCE_TYPE(tracer_language, T_STRING);
|
|
57
57
|
ENFORCE_TYPE(tracer_version, T_STRING);
|
|
@@ -59,17 +59,23 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
|
59
59
|
ENFORCE_TYPE(service_name, T_STRING);
|
|
60
60
|
ENFORCE_TYPE(service_env, T_STRING);
|
|
61
61
|
ENFORCE_TYPE(service_version, T_STRING);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
);
|
|
62
|
+
ENFORCE_TYPE(process_tags, T_STRING);
|
|
63
|
+
ENFORCE_TYPE(container_id, T_STRING);
|
|
64
|
+
|
|
65
|
+
void* builder = ddog_tracer_metadata_new();
|
|
66
|
+
|
|
67
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_RUNTIME_ID, StringValueCStr(runtime_id));
|
|
68
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_TRACER_LANGUAGE, StringValueCStr(tracer_language));
|
|
69
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_TRACER_VERSION, StringValueCStr(tracer_version));
|
|
70
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_HOSTNAME, StringValueCStr(hostname));
|
|
71
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_SERVICE_NAME, StringValueCStr(service_name));
|
|
72
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_SERVICE_ENV, StringValueCStr(service_env));
|
|
73
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_SERVICE_VERSION, StringValueCStr(service_version));
|
|
74
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_PROCESS_TAGS, StringValueCStr(process_tags));
|
|
75
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_CONTAINER_ID, StringValueCStr(container_id));
|
|
76
|
+
|
|
77
|
+
ddog_Result_TracerMemfdHandle result = ddog_tracer_metadata_store(builder);
|
|
78
|
+
ddog_tracer_metadata_free(builder);
|
|
73
79
|
|
|
74
80
|
if (result.tag == DDOG_RESULT_TRACER_MEMFD_HANDLE_ERR_TRACER_MEMFD_HANDLE) {
|
|
75
81
|
rb_funcall(logger, rb_intern("debug"), 1, rb_sprintf("Failed to store the tracer configuration in a memory file descriptor: %"PRIsVALUE, get_error_details_and_drop(&result.err)));
|
|
@@ -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 = '~> 25.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.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "json"
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module AIGuard
|
|
9
|
+
# API Client for AI Guard API.
|
|
10
|
+
# Uses net/http to perform request. Raises on client and server errors.
|
|
11
|
+
class APIClient
|
|
12
|
+
DEFAULT_SITE = "app.datadoghq.com"
|
|
13
|
+
DEFAULT_PATH = "/api/v2/ai-guard"
|
|
14
|
+
|
|
15
|
+
def initialize(endpoint:, api_key:, application_key:, timeout:)
|
|
16
|
+
@timeout = timeout
|
|
17
|
+
|
|
18
|
+
@endpoint_uri = if endpoint
|
|
19
|
+
URI(endpoint) #: URI::HTTP
|
|
20
|
+
else
|
|
21
|
+
URI::HTTPS.build(
|
|
22
|
+
host: Datadog.configuration.site || DEFAULT_SITE,
|
|
23
|
+
path: DEFAULT_PATH
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
@headers = {
|
|
28
|
+
"DD-API-KEY": api_key.to_s,
|
|
29
|
+
"DD-APPLICATION-KEY": application_key.to_s,
|
|
30
|
+
"DD-AI-GUARD-VERSION": Datadog::VERSION::STRING,
|
|
31
|
+
"DD-AI-GUARD-SOURCE": "SDK",
|
|
32
|
+
"DD-AI-GUARD-LANGUAGE": "ruby",
|
|
33
|
+
"content-type": "application/json"
|
|
34
|
+
}.freeze
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def post(path, body:)
|
|
38
|
+
Net::HTTP.start(@endpoint_uri.host.to_s, @endpoint_uri.port, use_ssl: use_ssl?, read_timeout: @timeout) do |http|
|
|
39
|
+
request = Net::HTTP::Post.new(@endpoint_uri.request_uri + path, @headers)
|
|
40
|
+
request.body = body.to_json
|
|
41
|
+
|
|
42
|
+
response = http.request(request)
|
|
43
|
+
raise_on_http_error!(response)
|
|
44
|
+
|
|
45
|
+
parse_response_body(response.body)
|
|
46
|
+
end
|
|
47
|
+
rescue Net::ReadTimeout
|
|
48
|
+
raise AIGuardClientError, "Request to AI Guard timed out"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def raise_on_http_error!(response)
|
|
54
|
+
case response
|
|
55
|
+
when Net::HTTPSuccess
|
|
56
|
+
# do nothing
|
|
57
|
+
when Net::HTTPRedirection
|
|
58
|
+
raise AIGuardClientError, "Redirects for AI Guard API are not supported"
|
|
59
|
+
else
|
|
60
|
+
error_message = begin
|
|
61
|
+
parsed_body = JSON.parse(response.body)
|
|
62
|
+
Array(parsed_body.fetch('errors')).join(', ')
|
|
63
|
+
rescue JSON::ParserError, KeyError
|
|
64
|
+
response.body
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
raise AIGuardClientError, error_message
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def parse_response_body(body)
|
|
72
|
+
JSON.parse(body)
|
|
73
|
+
rescue JSON::ParserError
|
|
74
|
+
raise AIGuardClientError, "Could not parse response body"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def use_ssl?
|
|
78
|
+
@endpoint_uri.scheme == 'https'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'api_client'
|
|
4
|
+
require_relative 'evaluation'
|
|
5
|
+
require_relative 'evaluation/request'
|
|
6
|
+
require_relative 'evaluation/result'
|
|
7
|
+
require_relative 'evaluation/no_op_result'
|
|
8
|
+
require_relative 'evaluation/message'
|
|
9
|
+
require_relative 'evaluation/tool_call'
|
|
10
|
+
require_relative 'ext'
|
|
11
|
+
|
|
12
|
+
module Datadog
|
|
13
|
+
module AIGuard
|
|
14
|
+
# Component for API Guard product
|
|
15
|
+
class Component
|
|
16
|
+
attr_reader :api_client, :logger
|
|
17
|
+
|
|
18
|
+
def self.build(settings, logger:, telemetry:)
|
|
19
|
+
return unless settings.respond_to?(:ai_guard) && settings.ai_guard.enabled
|
|
20
|
+
|
|
21
|
+
api_client = APIClient.new(
|
|
22
|
+
endpoint: settings.ai_guard.endpoint,
|
|
23
|
+
api_key: settings.api_key,
|
|
24
|
+
application_key: settings.ai_guard.app_key,
|
|
25
|
+
timeout: settings.ai_guard.timeout_ms / 1_000
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
new(api_client, logger: logger, telemetry: telemetry)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize(api_client, logger:, telemetry:)
|
|
32
|
+
@api_client = api_client
|
|
33
|
+
@logger = logger
|
|
34
|
+
@telemetry = telemetry
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def shutdown!
|
|
38
|
+
# no-op
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Configuration
|
|
6
|
+
# This module contains constants for AI Guard component
|
|
7
|
+
module Ext
|
|
8
|
+
ENV_AI_GUARD_ENABLED = "DD_AI_GUARD_ENABLED"
|
|
9
|
+
ENV_AI_GUARD_ENDPOINT = "DD_AI_GUARD_ENDPOINT"
|
|
10
|
+
ENV_AI_GUARD_TIMEOUT = "DD_AI_GUARD_TIMEOUT"
|
|
11
|
+
ENV_AI_GUARD_MAX_CONTENT_SIZE = "DD_AI_GUARD_MAX_CONTENT_SIZE"
|
|
12
|
+
ENV_AI_GUARD_MAX_MESSAGES_LENGTH = "DD_AI_GUARD_MAX_MESSAGES_LENGTH"
|
|
13
|
+
ENV_APP_KEY = "DD_APP_KEY"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
require_relative "ext"
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module AIGuard
|
|
8
|
+
module Configuration
|
|
9
|
+
# AI Guard specific settings
|
|
10
|
+
module Settings
|
|
11
|
+
def self.extended(base)
|
|
12
|
+
base = base.singleton_class unless base.is_a?(Class)
|
|
13
|
+
add_settings!(base)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.add_settings!(base)
|
|
17
|
+
base.class_eval do
|
|
18
|
+
# AI Guard specific configurations.
|
|
19
|
+
# @public_api
|
|
20
|
+
settings :ai_guard do
|
|
21
|
+
# Enable AI Guard.
|
|
22
|
+
#
|
|
23
|
+
# You can use this option to skip calls to AI Guard API without having to remove library as a whole.
|
|
24
|
+
#
|
|
25
|
+
# @default `DD_AI_GUARD_ENABLED`, otherwise `false`
|
|
26
|
+
# @return [Boolean]
|
|
27
|
+
option :enabled do |o|
|
|
28
|
+
o.type :bool
|
|
29
|
+
o.env Ext::ENV_AI_GUARD_ENABLED
|
|
30
|
+
o.default false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# AI Guard API endpoint path.
|
|
34
|
+
#
|
|
35
|
+
# @default `DD_AI_GUARD_ENDPOINT`, otherwise `nil`
|
|
36
|
+
# @return [String, nil]
|
|
37
|
+
option :endpoint do |o|
|
|
38
|
+
o.type :string, nilable: true
|
|
39
|
+
o.env Ext::ENV_AI_GUARD_ENDPOINT
|
|
40
|
+
|
|
41
|
+
o.setter do |value|
|
|
42
|
+
next unless value
|
|
43
|
+
|
|
44
|
+
uri = URI(value.to_s)
|
|
45
|
+
raise ArgumentError, "Please provide an absolute URI that includes a protocol" unless uri.absolute?
|
|
46
|
+
|
|
47
|
+
uri.to_s.delete_suffix("/")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Datadog Application key.
|
|
52
|
+
#
|
|
53
|
+
# @default `DD_APP_KEY` environment variable, otherwise `nil`
|
|
54
|
+
# @return [String, nil]
|
|
55
|
+
option :app_key do |o|
|
|
56
|
+
o.type :string, nilable: true
|
|
57
|
+
o.env Ext::ENV_APP_KEY
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Request timeout in milliseconds.
|
|
61
|
+
#
|
|
62
|
+
# @default `DD_AI_GUARD_TIMEOUT`, otherwise 10 000 ms
|
|
63
|
+
# @return [Integer]
|
|
64
|
+
option :timeout_ms do |o|
|
|
65
|
+
o.type :int
|
|
66
|
+
o.env Ext::ENV_AI_GUARD_TIMEOUT
|
|
67
|
+
o.default 10_000
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Maximum content size in bytes.
|
|
71
|
+
# Content that exceeds the maximum allowed size is truncated before
|
|
72
|
+
# being stored in the current span context.
|
|
73
|
+
#
|
|
74
|
+
# @default `DD_AI_GUARD_MAX_CONTENT_SIZE`, otherwise 524 228 bytes
|
|
75
|
+
# @return [Integer]
|
|
76
|
+
option :max_content_size_bytes do |o|
|
|
77
|
+
o.type :int
|
|
78
|
+
o.env Ext::ENV_AI_GUARD_MAX_CONTENT_SIZE
|
|
79
|
+
o.default 512 * 1024
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Maximum number of messages.
|
|
83
|
+
# Older messages are omitted once the message limit is reached.
|
|
84
|
+
#
|
|
85
|
+
# @default `DD_AI_GUARD_MAX_MESSAGES_LENGTH`, otherwise 16 messages
|
|
86
|
+
# @return [Integer]
|
|
87
|
+
option :max_messages_length do |o|
|
|
88
|
+
o.type :int
|
|
89
|
+
o.env Ext::ENV_AI_GUARD_MAX_MESSAGES_LENGTH
|
|
90
|
+
o.default 16
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Message class for AI Guard
|
|
7
|
+
class Message
|
|
8
|
+
attr_reader :role, :content, :tool_call, :tool_call_id
|
|
9
|
+
|
|
10
|
+
def initialize(role:, content: nil, tool_call: nil, tool_call_id: nil)
|
|
11
|
+
raise ArgumentError, "Role must be set to a non-empty value" if role.to_s.empty?
|
|
12
|
+
|
|
13
|
+
@role = role.to_sym
|
|
14
|
+
@content = content
|
|
15
|
+
@tool_call = tool_call
|
|
16
|
+
@tool_call_id = tool_call_id
|
|
17
|
+
|
|
18
|
+
if @tool_call && !@tool_call.is_a?(ToolCall)
|
|
19
|
+
raise ArgumentError, "Expected an instance of #{ToolCall.name} for :tool_call argument"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Class for emulating AI Guard evaluation result when AI Guard is disabled.
|
|
7
|
+
class NoOpResult
|
|
8
|
+
attr_reader :action, :reason, :tags
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@action = Result::ALLOW_ACTION
|
|
12
|
+
@reason = "AI Guard is disabled"
|
|
13
|
+
@tags = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def allow?
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def deny?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def abort?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def blocking_enabled?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Request builds the request body from an array of messages and processes the response
|
|
7
|
+
class Request
|
|
8
|
+
REQUEST_PATH = "/evaluate"
|
|
9
|
+
|
|
10
|
+
attr_reader :serialized_messages
|
|
11
|
+
|
|
12
|
+
def initialize(messages)
|
|
13
|
+
@serialized_messages = serialize_messages(messages)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def perform
|
|
17
|
+
api_client = AIGuard.api_client
|
|
18
|
+
|
|
19
|
+
# This should never happen, as we are only calling this method when AI Guard is enabled,
|
|
20
|
+
# and this means the API Client was not initialized properly.
|
|
21
|
+
#
|
|
22
|
+
# Please report this at https://github.com/datadog/dd-trace-rb/blob/master/CONTRIBUTING.md#found-a-bug
|
|
23
|
+
raise "AI Guard API Client not initialized" unless api_client
|
|
24
|
+
|
|
25
|
+
raw_response = api_client.post(REQUEST_PATH, body: build_request_body)
|
|
26
|
+
|
|
27
|
+
Result.new(raw_response)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def build_request_body
|
|
33
|
+
{
|
|
34
|
+
data: {
|
|
35
|
+
attributes: {
|
|
36
|
+
messages: @serialized_messages,
|
|
37
|
+
meta: {
|
|
38
|
+
service: Datadog.configuration.service,
|
|
39
|
+
env: Datadog.configuration.env
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def serialize_messages(messages)
|
|
47
|
+
serialized_messages = []
|
|
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
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def serialize_message(message)
|
|
59
|
+
if message.tool_call
|
|
60
|
+
{
|
|
61
|
+
role: message.role,
|
|
62
|
+
tool_calls: [
|
|
63
|
+
{
|
|
64
|
+
id: message.tool_call.id,
|
|
65
|
+
function: {
|
|
66
|
+
name: message.tool_call.tool_name,
|
|
67
|
+
arguments: message.tool_call.arguments
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
elsif message.tool_call_id
|
|
73
|
+
{role: message.role, tool_call_id: message.tool_call_id, content: message.content}
|
|
74
|
+
else
|
|
75
|
+
{role: message.role, content: message.content}
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Wrapper class for evaluation API response
|
|
7
|
+
class Result
|
|
8
|
+
ALLOW_ACTION = "ALLOW"
|
|
9
|
+
DENY_ACTION = "DENY"
|
|
10
|
+
ABORT_ACTION = "ABORT"
|
|
11
|
+
|
|
12
|
+
attr_reader :action, :reason, :tags
|
|
13
|
+
|
|
14
|
+
def initialize(raw_response)
|
|
15
|
+
attributes = raw_response.fetch("data").fetch("attributes")
|
|
16
|
+
|
|
17
|
+
@action = attributes.fetch("action")
|
|
18
|
+
@reason = attributes.fetch("reason")
|
|
19
|
+
@tags = attributes.fetch("tags")
|
|
20
|
+
@is_blocking_enabled = attributes.fetch("is_blocking_enabled")
|
|
21
|
+
rescue KeyError => e
|
|
22
|
+
raise AIGuardClientError, "Missing key: \"#{e.key}\""
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def allow?
|
|
26
|
+
action == ALLOW_ACTION
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def deny?
|
|
30
|
+
action == DENY_ACTION
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def abort?
|
|
34
|
+
action == ABORT_ACTION
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def blocking_enabled?
|
|
38
|
+
!!@is_blocking_enabled
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module AIGuard
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Tool call class for AI Guard
|
|
7
|
+
class ToolCall
|
|
8
|
+
attr_reader :tool_name, :id, :arguments
|
|
9
|
+
|
|
10
|
+
def initialize(tool_name, id:, arguments:)
|
|
11
|
+
@tool_name = tool_name
|
|
12
|
+
@id = id
|
|
13
|
+
@arguments = arguments
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|