datadog 2.17.0 → 2.19.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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +90 -1
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +63 -56
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -76
  5. data/ext/datadog_profiling_native_extension/collectors_stack.h +20 -3
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +62 -12
  7. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
  8. data/ext/datadog_profiling_native_extension/extconf.rb +7 -0
  9. data/ext/datadog_profiling_native_extension/heap_recorder.c +239 -363
  10. data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
  11. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
  12. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
  13. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +38 -26
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -4
  15. data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
  16. data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -11
  17. data/ext/datadog_profiling_native_extension/stack_recorder.c +154 -57
  18. data/ext/libdatadog_api/extconf.rb +2 -2
  19. data/ext/libdatadog_api/library_config.c +54 -12
  20. data/ext/libdatadog_api/library_config.h +6 -0
  21. data/ext/libdatadog_api/process_discovery.c +2 -7
  22. data/ext/libdatadog_extconf_helpers.rb +1 -1
  23. data/lib/datadog/appsec/api_security/lru_cache.rb +9 -2
  24. data/lib/datadog/appsec/api_security/route_extractor.rb +71 -0
  25. data/lib/datadog/appsec/api_security/sampler.rb +59 -0
  26. data/lib/datadog/appsec/api_security.rb +14 -0
  27. data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
  28. data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
  29. data/lib/datadog/appsec/component.rb +30 -54
  30. data/lib/datadog/appsec/configuration/settings.rb +60 -2
  31. data/lib/datadog/appsec/context.rb +6 -6
  32. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
  33. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +27 -16
  34. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +1 -1
  35. data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
  36. data/lib/datadog/appsec/remote.rb +15 -55
  37. data/lib/datadog/appsec/security_engine/engine.rb +194 -0
  38. data/lib/datadog/appsec/security_engine/runner.rb +10 -11
  39. data/lib/datadog/appsec.rb +4 -7
  40. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  41. data/lib/datadog/core/configuration/agent_settings_resolver.rb +1 -43
  42. data/lib/datadog/core/configuration/components.rb +2 -4
  43. data/lib/datadog/core/configuration/option.rb +9 -9
  44. data/lib/datadog/core/configuration/settings.rb +42 -10
  45. data/lib/datadog/core/configuration/stable_config.rb +1 -2
  46. data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
  47. data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
  48. data/lib/datadog/core/process_discovery.rb +5 -1
  49. data/lib/datadog/core/remote/configuration/repository.rb +12 -0
  50. data/lib/datadog/core/tag_builder.rb +56 -0
  51. data/lib/datadog/core/telemetry/component.rb +8 -4
  52. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +1 -0
  53. data/lib/datadog/core/telemetry/event/app_started.rb +148 -40
  54. data/lib/datadog/core/telemetry/logger.rb +5 -4
  55. data/lib/datadog/core/telemetry/logging.rb +11 -5
  56. data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
  57. data/lib/datadog/core/transport/http/builder.rb +2 -2
  58. data/lib/datadog/core/transport/http/env.rb +8 -0
  59. data/lib/datadog/core/utils.rb +7 -0
  60. data/lib/datadog/di/instrumenter.rb +48 -5
  61. data/lib/datadog/di/probe_notification_builder.rb +37 -42
  62. data/lib/datadog/di/probe_notifier_worker.rb +9 -1
  63. data/lib/datadog/di/serializer.rb +10 -2
  64. data/lib/datadog/di/transport/http/input.rb +10 -0
  65. data/lib/datadog/di/transport/input.rb +10 -2
  66. data/lib/datadog/di.rb +0 -6
  67. data/lib/datadog/kit/appsec/events/v2.rb +195 -0
  68. data/lib/datadog/profiling/collectors/code_provenance.rb +17 -8
  69. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -0
  70. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
  71. data/lib/datadog/profiling/collectors/info.rb +41 -0
  72. data/lib/datadog/profiling/collectors/thread_context.rb +16 -1
  73. data/lib/datadog/profiling/component.rb +8 -9
  74. data/lib/datadog/profiling/exporter.rb +9 -3
  75. data/lib/datadog/profiling/ext.rb +0 -12
  76. data/lib/datadog/profiling/http_transport.rb +2 -2
  77. data/lib/datadog/profiling/profiler.rb +2 -0
  78. data/lib/datadog/profiling/scheduler.rb +2 -1
  79. data/lib/datadog/profiling/sequence_tracker.rb +44 -0
  80. data/lib/datadog/profiling/stack_recorder.rb +5 -5
  81. data/lib/datadog/profiling/tag_builder.rb +7 -37
  82. data/lib/datadog/profiling/tasks/setup.rb +2 -0
  83. data/lib/datadog/profiling.rb +1 -0
  84. data/lib/datadog/single_step_instrument.rb +9 -0
  85. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
  86. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
  87. data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
  88. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -1
  89. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
  90. data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
  91. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -6
  92. data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -1
  93. data/lib/datadog/tracing/contrib/rails/runner.rb +61 -40
  94. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  95. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
  96. data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
  97. data/lib/datadog/tracing/span_event.rb +1 -1
  98. data/lib/datadog/tracing/span_operation.rb +22 -0
  99. data/lib/datadog/tracing/sync_writer.rb +1 -1
  100. data/lib/datadog/tracing/trace_operation.rb +12 -4
  101. data/lib/datadog/tracing/tracer.rb +6 -2
  102. data/lib/datadog/version.rb +1 -1
  103. data/lib/datadog.rb +7 -0
  104. metadata +14 -10
  105. data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
  106. data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
  107. data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
  108. data/lib/datadog/appsec/processor.rb +0 -107
@@ -7,6 +7,10 @@
7
7
  static VALUE _native_configurator_new(VALUE klass);
8
8
  static VALUE _native_configurator_get(VALUE self);
9
9
 
10
+ // Used for testing in RSpec
11
+ static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
12
+ static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
13
+
10
14
  static VALUE config_vec_class = Qnil;
11
15
 
12
16
  // ddog_Configurator memory management
@@ -52,20 +56,42 @@ void library_config_init(VALUE core_module) {
52
56
  rb_define_alloc_func(configurator_class, _native_configurator_new);
53
57
  rb_define_method(configurator_class, "get", _native_configurator_get, 0);
54
58
 
59
+ // Used for testing in RSpec
60
+ VALUE testing_module = rb_define_module_under(stable_config_module, "Testing");
61
+ rb_define_singleton_method(testing_module, "with_local_path", _native_configurator_with_local_path, 2);
62
+ rb_define_singleton_method(testing_module, "with_fleet_path", _native_configurator_with_fleet_path, 2);
63
+
55
64
  rb_undef_alloc_func(config_vec_class); // It cannot be created from Ruby code and only serves as an intermediate object for the Ruby GC
56
65
  }
57
66
 
58
- // TODO: After libdatadog 17.1 release, delete rb_raise, uncomment code and change `DDTRACE_UNUSED VALUE _klass` by `VALUE klass`
59
- static VALUE _native_configurator_new(DDTRACE_UNUSED VALUE _klass) {
60
- /*
67
+ static VALUE _native_configurator_new(VALUE klass) {
61
68
  ddog_Configurator *configurator = ddog_library_configurator_new(false, DDOG_CHARSLICE_C("ruby"));
62
69
 
63
70
  ddog_library_configurator_with_detect_process_info(configurator);
64
71
 
65
72
  return TypedData_Wrap_Struct(klass, &configurator_typed_data, configurator);
66
- */
73
+ }
74
+
75
+ static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path) {
76
+ ddog_Configurator *configurator;
77
+ TypedData_Get_Struct(rb_configurator, ddog_Configurator, &configurator_typed_data, configurator);
78
+
79
+ ENFORCE_TYPE(path, T_STRING);
67
80
 
68
- rb_raise(rb_eNotImpError, "TODO: Not in use yet, waiting for libdatadog 17.1");
81
+ ddog_library_configurator_with_local_path(configurator, cstr_from_ruby_string(path));
82
+
83
+ return Qnil;
84
+ }
85
+
86
+ static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path) {
87
+ ddog_Configurator *configurator;
88
+ TypedData_Get_Struct(rb_configurator, ddog_Configurator, &configurator_typed_data, configurator);
89
+
90
+ ENFORCE_TYPE(path, T_STRING);
91
+
92
+ ddog_library_configurator_with_fleet_path(configurator, cstr_from_ruby_string(path));
93
+
94
+ return Qnil;
69
95
  }
70
96
 
71
97
  static VALUE _native_configurator_get(VALUE self) {
@@ -96,26 +122,42 @@ static VALUE _native_configurator_get(VALUE self) {
96
122
 
97
123
  VALUE local_config_hash = rb_hash_new();
98
124
  VALUE fleet_config_hash = rb_hash_new();
99
- // TODO: Uncomment next block after libdatadog 17.1 release
100
- /*
125
+
126
+ bool local_config_id_set = false;
127
+ bool fleet_config_id_set = false;
128
+ VALUE local_hash = rb_hash_new();
129
+ VALUE fleet_hash = rb_hash_new();
101
130
  for (uintptr_t i = 0; i < config_vec->len; i++) {
102
131
  ddog_LibraryConfig config = config_vec->ptr[i];
103
132
  VALUE selected_hash;
104
133
  if (config.source == DDOG_LIBRARY_CONFIG_SOURCE_LOCAL_STABLE_CONFIG) {
105
134
  selected_hash = local_config_hash;
135
+ if (!local_config_id_set) {
136
+ local_config_id_set = true;
137
+ if (config.config_id.length > 0) {
138
+ rb_hash_aset(local_hash, ID2SYM(rb_intern("id")), rb_utf8_str_new_cstr(config.config_id.ptr));
139
+ }
140
+ }
106
141
  }
107
142
  else {
108
143
  selected_hash = fleet_config_hash;
144
+ if (!fleet_config_id_set) {
145
+ fleet_config_id_set = true;
146
+ if (config.config_id.length > 0) {
147
+ rb_hash_aset(fleet_hash, ID2SYM(rb_intern("id")), rb_utf8_str_new_cstr(config.config_id.ptr));
148
+ }
149
+ }
109
150
  }
110
151
 
111
- ddog_CStr name = ddog_library_config_name_to_env(config.name);
112
- rb_hash_aset(selected_hash, rb_str_new(name.ptr, name.length), rb_str_new(config.value.ptr, config.value.length));
152
+ rb_hash_aset(selected_hash, rb_utf8_str_new_cstr(config.name.ptr), rb_utf8_str_new_cstr(config.value.ptr));
113
153
  }
114
- */
154
+
155
+ rb_hash_aset(local_hash, ID2SYM(rb_intern("config")), local_config_hash);
156
+ rb_hash_aset(fleet_hash, ID2SYM(rb_intern("config")), fleet_config_hash);
115
157
 
116
158
  VALUE result = rb_hash_new();
117
- rb_hash_aset(result, ID2SYM(rb_intern("local")), local_config_hash);
118
- rb_hash_aset(result, ID2SYM(rb_intern("fleet")), fleet_config_hash);
159
+ rb_hash_aset(result, ID2SYM(rb_intern("local")), local_hash);
160
+ rb_hash_aset(result, ID2SYM(rb_intern("fleet")), fleet_hash);
119
161
 
120
162
  RB_GC_GUARD(config_vec_rb);
121
163
  return result;
@@ -17,3 +17,9 @@ static inline VALUE log_warning_without_config(VALUE warning) {
17
17
 
18
18
  return rb_funcall(logger, rb_intern("warn"), 1, warning);
19
19
  }
20
+
21
+ static inline ddog_CStr cstr_from_ruby_string(VALUE string) {
22
+ ENFORCE_TYPE(string, T_STRING);
23
+ ddog_CStr cstr = {.ptr = RSTRING_PTR(string), .length = RSTRING_LEN(string)};
24
+ return cstr;
25
+ }
@@ -1,7 +1,7 @@
1
1
  #include <errno.h>
2
2
  #include <stdlib.h>
3
3
  #include <ruby.h>
4
- #include <datadog/common.h>
4
+ #include <datadog/library-config.h>
5
5
 
6
6
  #include "datadog_ruby_common.h"
7
7
 
@@ -36,8 +36,7 @@ void process_discovery_init(VALUE core_module) {
36
36
  rb_define_singleton_method(process_discovery_class, "_native_close_tracer_memfd", _native_close_tracer_memfd, 2);
37
37
  }
38
38
 
39
- // TODO: Remove DDTRACE_UNUSED and rename _self to self once we have updated libdatadog to 17.1
40
- static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
39
+ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
41
40
  VALUE logger;
42
41
  VALUE options;
43
42
  rb_scan_args(argc, argv, "1:", &logger, &options);
@@ -61,7 +60,6 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED
61
60
  ENFORCE_TYPE(service_env, T_STRING);
62
61
  ENFORCE_TYPE(service_version, T_STRING);
63
62
 
64
- /*
65
63
  ddog_Result_TracerMemfdHandle result = ddog_store_tracer_metadata(
66
64
  (uint8_t) NUM2UINT(schema_version),
67
65
  char_slice_from_ruby_string(runtime_id),
@@ -86,9 +84,6 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED
86
84
  VALUE tracer_memfd_class = rb_const_get(self, rb_intern("TracerMemfd"));
87
85
  VALUE tracer_memfd = TypedData_Wrap_Struct(tracer_memfd_class, &tracer_memfd_type, fd);
88
86
  return tracer_memfd;
89
- */
90
-
91
- rb_raise(rb_eNotImpError, "TODO: Not in use yet, waiting for libdatadog 17.1");
92
87
  }
93
88
 
94
89
  static VALUE _native_to_rb_int(DDTRACE_UNUSED VALUE _self, VALUE tracer_memfd) {
@@ -104,7 +104,7 @@ module Datadog
104
104
 
105
105
  # mkmf sets $PKGCONFIG after the `pkg_config` gets used in extconf.rb. When `pkg_config` is unsuccessful, we use
106
106
  # this helper to decide if we can show more specific error message vs a generic "something went wrong".
107
- def self.pkg_config_missing?(command: $PKGCONFIG) # rubocop:disable Style/GlobalVars
107
+ def self.pkg_config_missing?(command: $PKGCONFIG) # standard:disable Style/GlobalVars
108
108
  pkg_config_available = command && xsystem("#{command} --version")
109
109
 
110
110
  pkg_config_available != true
@@ -30,6 +30,14 @@ module Datadog
30
30
  end
31
31
  end
32
32
 
33
+ def store(key, value)
34
+ return @store[key] = value if @store.delete(key)
35
+
36
+ # NOTE: evict the oldest entry if store reached the maximum allowed size
37
+ @store.shift if @store.size >= @max_size
38
+ @store[key] = value
39
+ end
40
+
33
41
  # NOTE: If the key exists, it's moved to the end of the list and
34
42
  # if does not, the given block will be executed and the result
35
43
  # will be stored (which will add it to the end of the list).
@@ -40,8 +48,7 @@ module Datadog
40
48
 
41
49
  # NOTE: evict the oldest entry if store reached the maximum allowed size
42
50
  @store.shift if @store.size >= @max_size
43
-
44
- @store[key] ||= yield
51
+ @store[key] = yield
45
52
  end
46
53
  end
47
54
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module APISecurity
6
+ # This is a helper module to extract the route pattern from the Rack::Request.
7
+ module RouteExtractor
8
+ SINATRA_ROUTE_KEY = 'sinatra.route'
9
+ SINATRA_ROUTE_SEPARATOR = ' '
10
+ GRAPE_ROUTE_KEY = 'grape.routing_args'
11
+ RAILS_ROUTE_KEY = 'action_dispatch.route_uri_pattern'
12
+ RAILS_ROUTES_KEY = 'action_dispatch.routes'
13
+ RAILS_PATH_PARAMS_KEY = 'action_dispatch.request.path_parameters'
14
+ RAILS_FORMAT_SUFFIX = '(.:format)'
15
+
16
+ # HACK: We rely on the fact that each contrib will modify `request.env`
17
+ # and store information sufficient to compute the canonical
18
+ # route (ex: `/users/:id`).
19
+ #
20
+ # When contribs like Sinatra or Grape are used, they could be mounted
21
+ # into the Rails app, hence you can see the use of the `script_name`
22
+ # that will contain the path prefix of the mounted app.
23
+ #
24
+ # Rack
25
+ # does not support named arguments, so we have to use `path`
26
+ # Sinatra
27
+ # uses `sinatra.route` with a string like "GET /users/:id"
28
+ # Grape
29
+ # uses `grape.routing_args` with a hash with a `:route_info` key
30
+ # that contains a `Grape::Router::Route` object that contains
31
+ # `Grape::Router::Pattern` object with an `origin` method
32
+ # Rails < 7.1 (slow path)
33
+ # uses `action_dispatch.routes` to store `ActionDispatch::Routing::RouteSet`
34
+ # which can recognize requests
35
+ # Rails > 7.1 (fast path)
36
+ # uses `action_dispatch.route_uri_pattern` with a string like
37
+ # "/users/:id(.:format)"
38
+ #
39
+ # WARNING: This method works only *after* the request has been routed.
40
+ #
41
+ # WARNING: In Rails > 7.1 when a route was not found,
42
+ # action_dispatch.route_uri_pattern will not be set.
43
+ # In Rails < 7.1 it also will not be set even if a route was found,
44
+ # but in this case action_dispatch.request.path_parameters won't be empty.
45
+ def self.route_pattern(request)
46
+ if request.env.key?(GRAPE_ROUTE_KEY)
47
+ pattern = request.env[GRAPE_ROUTE_KEY][:route_info]&.pattern&.origin
48
+ "#{request.script_name}#{pattern}"
49
+ elsif request.env.key?(SINATRA_ROUTE_KEY)
50
+ pattern = request.env[SINATRA_ROUTE_KEY].split(SINATRA_ROUTE_SEPARATOR, 2)[1]
51
+ "#{request.script_name}#{pattern}"
52
+ elsif request.env.key?(RAILS_ROUTE_KEY)
53
+ request.env[RAILS_ROUTE_KEY].delete_suffix(RAILS_FORMAT_SUFFIX)
54
+ elsif request.env.key?(RAILS_ROUTES_KEY) && !request.env.fetch(RAILS_PATH_PARAMS_KEY, {}).empty?
55
+ pattern = request.env[RAILS_ROUTES_KEY].router
56
+ .recognize(request) { |route, _| break route.path.spec.to_s }
57
+
58
+ # NOTE: If rails is unable to recognize request it returns empty Array
59
+ pattern = nil if pattern&.empty?
60
+
61
+ # NOTE: If rails can't recognize the request, we are going to fallback
62
+ # to generic request path
63
+ (pattern || request.path).delete_suffix(RAILS_FORMAT_SUFFIX)
64
+ else
65
+ request.path
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zlib'
4
+ require_relative 'lru_cache'
5
+ require_relative 'route_extractor'
6
+ require_relative '../../core/utils/time'
7
+
8
+ module Datadog
9
+ module AppSec
10
+ module APISecurity
11
+ # A thread-local sampler for API security based on defined delay between
12
+ # samples with caching capability.
13
+ class Sampler
14
+ THREAD_KEY = :datadog_appsec_api_security_sampler
15
+ MAX_CACHE_SIZE = 4096
16
+
17
+ class << self
18
+ def thread_local
19
+ sampler = Thread.current.thread_variable_get(THREAD_KEY)
20
+ return sampler unless sampler.nil?
21
+
22
+ Thread.current.thread_variable_set(THREAD_KEY, new(sample_delay))
23
+ end
24
+
25
+ # @api private
26
+ def reset!
27
+ Thread.current.thread_variable_set(THREAD_KEY, nil)
28
+ end
29
+
30
+ private
31
+
32
+ def sample_delay
33
+ Datadog.configuration.appsec.api_security.sample_delay
34
+ end
35
+ end
36
+
37
+ def initialize(sample_delay)
38
+ raise ArgumentError, 'sample_delay must be an Integer' unless sample_delay.is_a?(Integer)
39
+
40
+ @cache = LRUCache.new(MAX_CACHE_SIZE)
41
+ @sample_delay_seconds = sample_delay
42
+ end
43
+
44
+ def sample?(request, response)
45
+ return true if @sample_delay_seconds.zero?
46
+
47
+ key = Zlib.crc32("#{request.request_method}#{RouteExtractor.route_pattern(request)}#{response.status}")
48
+ current_timestamp = Core::Utils::Time.now.to_i
49
+ cached_timestamp = @cache[key] || 0
50
+
51
+ return false if current_timestamp - cached_timestamp <= @sample_delay_seconds
52
+
53
+ @cache.store(key, current_timestamp)
54
+ true
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,9 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'api_security/sampler'
4
+
3
5
  module Datadog
4
6
  module AppSec
5
7
  # A namespace for API Security features.
6
8
  module APISecurity
9
+ def self.enabled?
10
+ Datadog.configuration.appsec.api_security.enabled?
11
+ end
12
+
13
+ def self.sample?(request, response)
14
+ Sampler.thread_local.sample?(request, response)
15
+ end
16
+
17
+ def self.sample_trace?(trace)
18
+ # NOTE: Reads as "if trace is priority sampled or if in standalone mode"
19
+ trace&.priority_sampled? || !Datadog.configuration.apm.tracing.enabled
20
+ end
7
21
  end
8
22
  end
9
23
  end