datadog 2.6.0 → 2.7.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23fdb98e800ed71c28238b4b61e7f1187b27833d8e98c14e0f60d43ce838d4cd
4
- data.tar.gz: ed99ae40d1e94aedcf27f8bcdeb70059c02ad116e8648621e37d22d5be1f69ad
3
+ metadata.gz: '00617590b3381113b74dde6671802aad74e6ffee0a96737fbc04149515c6a79d'
4
+ data.tar.gz: 5bed675aca238d308051ba0a728209e2a4a5ba17f2dc11a52eacee8aaf55a123
5
5
  SHA512:
6
- metadata.gz: df3d8bc5efb89bb7a893b006484d3d826acf7beb57d6abbf8b25c2e9a277a95f7f681d6262d5dd08485aaf5526c677edf641711435e67674f1043c1fbf1ba55f
7
- data.tar.gz: 02b397ae85a8ced3f6112beb899826c86ba137be36c229a85150cdc708dadd937e9860775bdfd02d7475bb4f7c890b1019901ec146acb5ad21bdd192906aa339
6
+ metadata.gz: 4097896d2d8126418f0827b9c4ad916a003e71ead0919fae2b3586415540f869d58f140865d4c625d20fd4de6a76bcf667156893e7c01f0fee981b7fcb6cafe9
7
+ data.tar.gz: ce91b73f91a97db31570bd92dab0ca26bf7a6b849d67b774a4efacea0ec93e19f19c27a3dc3f0f232f2adce6cf5ed13b510c30651c529a6b402137944a6b2e87
data/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.7.1] - 2024-11-28
6
+
7
+ ### Fixed
8
+
9
+ * Tracing: Fix missing version tag ([#4075][])
10
+ * Profiling: Fix profiling not loading in certain situations on Ruby 2.5 and 3.3 ([#4161][])
11
+
12
+ ## [2.7.0] - 2024-11-13
13
+
14
+ ### Added
15
+
16
+ * Profiling: Enable "heap clean after GC" profiler optimization by default ([#4085][])
17
+
18
+ ### Changed
19
+
20
+ * Enable crashtracking by default ([#4083][])
21
+ * Upgrade to `libdatadog` 14.1 ([#4082][])
22
+
23
+ ### Fixed
24
+
25
+ * Fix `Process.waitall` hanging and stack overflow when crashtracking enabled ([#4082][])
26
+
5
27
  ## [2.6.0] - 2024-11-06
6
28
 
7
29
  ### Changed
@@ -3013,7 +3035,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3013
3035
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3014
3036
 
3015
3037
 
3016
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.6.0...master
3038
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.7.0...master
3039
+ [2.7.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.6.0...v2.7.0
3017
3040
  [2.6.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.5.0...v2.6.0
3018
3041
  [2.5.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.4.0...v2.5.0
3019
3042
  [2.4.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.3.0...v2.4.0
@@ -4457,7 +4480,12 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4457
4480
  [#4027]: https://github.com/DataDog/dd-trace-rb/issues/4027
4458
4481
  [#4033]: https://github.com/DataDog/dd-trace-rb/issues/4033
4459
4482
  [#4065]: https://github.com/DataDog/dd-trace-rb/issues/4065
4483
+ [#4075]: https://github.com/DataDog/dd-trace-rb/issues/4075
4460
4484
  [#4078]: https://github.com/DataDog/dd-trace-rb/issues/4078
4485
+ [#4082]: https://github.com/DataDog/dd-trace-rb/issues/4082
4486
+ [#4083]: https://github.com/DataDog/dd-trace-rb/issues/4083
4487
+ [#4085]: https://github.com/DataDog/dd-trace-rb/issues/4085
4488
+ [#4161]: https://github.com/DataDog/dd-trace-rb/issues/4161
4461
4489
  [@AdrianLC]: https://github.com/AdrianLC
4462
4490
  [@Azure7111]: https://github.com/Azure7111
4463
4491
  [@BabyGroot]: https://github.com/BabyGroot
@@ -131,6 +131,9 @@ end
131
131
 
132
132
  have_func "malloc_stats"
133
133
 
134
+ # On Ruby 2.5 and 3.3, this symbol was not visible. It is on 2.6 to 3.2, as well as 3.4+
135
+ $defs << "-DNO_RB_OBJ_INFO" if RUBY_VERSION.start_with?("2.5", "3.3")
136
+
134
137
  # On older Rubies, rb_postponed_job_preregister/rb_postponed_job_trigger did not exist
135
138
  $defs << "-DNO_POSTPONED_TRIGGER" if RUBY_VERSION < "3.3"
136
139
 
@@ -587,16 +587,13 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *st
587
587
  // Taken from upstream vm_insnhelper.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
588
588
  // Copyright (C) 2007 Koichi Sasada
589
589
  // to support our custom rb_profile_frames (see above)
590
- // Modifications: None
590
+ // Modifications:
591
+ // * Removed debug checks (they were ifdef'd out anyway)
591
592
  static rb_callable_method_entry_t *
592
593
  check_method_entry(VALUE obj, int can_be_svar)
593
594
  {
594
595
  if (obj == Qfalse) return NULL;
595
596
 
596
- #if VM_CHECK_MODE > 0
597
- if (!RB_TYPE_P(obj, T_IMEMO)) rb_bug("check_method_entry: unknown type: %s", rb_obj_info(obj));
598
- #endif
599
-
600
597
  switch (imemo_type(obj)) {
601
598
  case imemo_ment:
602
599
  return (rb_callable_method_entry_t *)obj;
@@ -608,9 +605,6 @@ check_method_entry(VALUE obj, int can_be_svar)
608
605
  }
609
606
  // fallthrough
610
607
  default:
611
- #if VM_CHECK_MODE > 0
612
- rb_bug("check_method_entry: svar should not be there:");
613
- #endif
614
608
  return NULL;
615
609
  }
616
610
  }
@@ -37,6 +37,7 @@ static VALUE _native_trigger_holding_the_gvl_signal_handler_on(DDTRACE_UNUSED VA
37
37
  static VALUE _native_enforce_success(DDTRACE_UNUSED VALUE _self, VALUE syserr_errno, VALUE with_gvl);
38
38
  static void *trigger_enforce_success(void *trigger_args);
39
39
  static VALUE _native_malloc_stats(DDTRACE_UNUSED VALUE _self);
40
+ static VALUE _native_safe_object_info(DDTRACE_UNUSED VALUE _self, VALUE obj);
40
41
 
41
42
  void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
42
43
  VALUE datadog_module = rb_define_module("Datadog");
@@ -72,6 +73,7 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
72
73
  rb_define_singleton_method(testing_module, "_native_trigger_holding_the_gvl_signal_handler_on", _native_trigger_holding_the_gvl_signal_handler_on, 1);
73
74
  rb_define_singleton_method(testing_module, "_native_enforce_success", _native_enforce_success, 2);
74
75
  rb_define_singleton_method(testing_module, "_native_malloc_stats", _native_malloc_stats, 0);
76
+ rb_define_singleton_method(testing_module, "_native_safe_object_info", _native_safe_object_info, 1);
75
77
  }
76
78
 
77
79
  static VALUE native_working_p(DDTRACE_UNUSED VALUE _self) {
@@ -265,3 +267,7 @@ static VALUE _native_malloc_stats(DDTRACE_UNUSED VALUE _self) {
265
267
  return Qfalse;
266
268
  #endif
267
269
  }
270
+
271
+ static VALUE _native_safe_object_info(DDTRACE_UNUSED VALUE _self, VALUE obj) {
272
+ return rb_str_new_cstr(safe_object_info(obj));
273
+ }
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "ruby_helpers.h"
5
5
  #include "private_vm_api_access.h"
6
+ #include "extconf.h"
6
7
 
7
8
  // The following global variables are initialized at startup to save expensive lookups later.
8
9
  // They are not expected to be mutated outside of init.
@@ -219,17 +220,26 @@ static bool ruby_is_obj_with_class(VALUE obj) {
219
220
  return false;
220
221
  }
221
222
 
222
- // These two functions are not present in the VM headers, but are public symbols that can be invoked.
223
+ // This function is not present in the VM headers, but is a public symbol that can be invoked.
223
224
  int rb_objspace_internal_object_p(VALUE obj);
224
- const char *rb_obj_info(VALUE obj);
225
+
226
+ #ifdef NO_RB_OBJ_INFO
227
+ const char* safe_object_info(DDTRACE_UNUSED VALUE obj) { return "(No rb_obj_info for current Ruby)"; }
228
+ #else
229
+ // This function is a public symbol, but not on all Rubies; `safe_object_info` below abstracts this, and
230
+ // should be used instead.
231
+ const char *rb_obj_info(VALUE obj);
232
+
233
+ const char* safe_object_info(VALUE obj) { return rb_obj_info(obj); }
234
+ #endif
225
235
 
226
236
  VALUE ruby_safe_inspect(VALUE obj) {
227
237
  if (!ruby_is_obj_with_class(obj)) return rb_str_new_cstr("(Not an object)");
228
- if (rb_objspace_internal_object_p(obj)) return rb_sprintf("(VM Internal, %s)", rb_obj_info(obj));
238
+ if (rb_objspace_internal_object_p(obj)) return rb_sprintf("(VM Internal, %s)", safe_object_info(obj));
229
239
  // @ivoanjo: I saw crashes on Ruby 3.1.4 when trying to #inspect matchdata objects. I'm not entirely sure why this
230
240
  // is needed, but since we only use this method for debug purposes I put in this alternative and decided not to
231
241
  // dig deeper.
232
- if (rb_type(obj) == RUBY_T_MATCH) return rb_sprintf("(MatchData, %s)", rb_obj_info(obj));
242
+ if (rb_type(obj) == RUBY_T_MATCH) return rb_sprintf("(MatchData, %s)", safe_object_info(obj));
233
243
  if (rb_respond_to(obj, inspect_id)) return rb_sprintf("%+"PRIsVALUE, obj);
234
244
  if (rb_respond_to(obj, to_s_id)) return rb_sprintf("%"PRIsVALUE, obj);
235
245
 
@@ -90,3 +90,7 @@ size_t ruby_obj_memsize_of(VALUE obj);
90
90
  // return a string with the result of that call. Elsif the object responds to
91
91
  // 'to_s', return a string with the result of that call. Otherwise, return Qnil.
92
92
  VALUE ruby_safe_inspect(VALUE obj);
93
+
94
+ // You probably want ruby_safe_inspect instead; this is a lower-level dependency
95
+ // of it, that's being exposed here just to facilitate testing.
96
+ const char* safe_object_info(VALUE obj);
@@ -58,16 +58,18 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
58
58
 
59
59
  ddog_crasht_Config config = {
60
60
  .additional_files = {},
61
- // The Ruby VM already uses an alt stack to detect stack overflows so the crash handler must not overwrite it.
61
+ // @ivoanjo: The Ruby VM already uses an alt stack to detect stack overflows.
62
62
  //
63
- // @ivoanjo: Specifically, with `create_alt_stack = true` I saw a segfault, such as Ruby 2.6's bug with
63
+ // In libdatadog < 14 with `create_alt_stack = true` I saw a segfault, such as Ruby 2.6's bug with
64
64
  // "Process.detach(fork { exit! }).instance_variable_get(:@foo)" being turned into a
65
65
  // "-e:1:in `instance_variable_get': stack level too deep (SystemStackError)" by Ruby.
66
- //
67
66
  // The Ruby crash handler also seems to get confused when this option is enabled and
68
67
  // "Process.kill('SEGV', Process.pid)" gets run.
68
+ //
69
+ // This actually changed in libdatadog 14, so I could see no issues with `create_alt_stack = true`, but not
70
+ // overridding what Ruby set up seems a saner default to keep anyway.
69
71
  .create_alt_stack = false,
70
- .use_alt_stack = true, // NOTE: This is a no-op in libdatadog 14.0; should be fixed in a future version
72
+ .use_alt_stack = true,
71
73
  .endpoint = endpoint,
72
74
  .resolve_frames = DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER,
73
75
  .timeout_ms = FIX2INT(upload_timeout_seconds) * 1000,
@@ -8,7 +8,7 @@ module Datadog
8
8
  module LibdatadogExtconfHelpers
9
9
  # Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
10
10
  # may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
11
- LIBDATADOG_VERSION = '~> 14.0.0.1.0'
11
+ LIBDATADOG_VERSION = '~> 14.1.0.1.0'
12
12
 
13
13
  # Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
14
14
  # libdatadog are moved after the extension gets compiled.
@@ -518,13 +518,13 @@ module Datadog
518
518
  # Controls if the heap profiler should attempt to clean young objects after GC, rather than just at
519
519
  # serialization time. This lowers memory usage and high percentile latency.
520
520
  #
521
- # Only takes effect when used together with `gc_enabled: true` and `experimental_heap_enabled: true`.
521
+ # Only has effect when used together with `gc_enabled: true` and `experimental_heap_enabled: true`.
522
522
  #
523
- # @default false
523
+ # @default true
524
524
  option :heap_clean_after_gc_enabled do |o|
525
525
  o.type :bool
526
526
  o.env 'DD_PROFILING_HEAP_CLEAN_AFTER_GC_ENABLED'
527
- o.default false
527
+ o.default true
528
528
  end
529
529
  end
530
530
 
@@ -927,7 +927,7 @@ module Datadog
927
927
  # Enables reporting of information when Ruby VM crashes.
928
928
  option :enabled do |o|
929
929
  o.type :bool
930
- o.default false
930
+ o.default true
931
931
  o.env 'DD_CRASHTRACKING_ENABLED'
932
932
  end
933
933
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Lint/AssignmentInCondition
4
+
3
5
  module Datadog
4
6
  module DI
5
7
  # Tracks loaded Ruby code by source file and maintains a map from
@@ -77,6 +79,26 @@ module Datadog
77
79
  registry[path] = tp.instruction_sequence
78
80
  end
79
81
  end
82
+
83
+ DI.component&.probe_manager&.install_pending_line_probes(path)
84
+
85
+ # Since this method normally is called from customer applications,
86
+ # rescue any exceptions that might not be handled to not break said
87
+ # customer applications.
88
+ rescue => exc
89
+ # TODO we do not have DI.component defined yet, remove steep:ignore
90
+ # before release.
91
+ if component = DI.component # steep:ignore
92
+ raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
93
+ component.logger.warn("Unhandled exception in script_compiled trace point: #{exc.class}: #{exc}")
94
+ component.telemetry&.report(exc, description: "Unhandled exception in script_compiled trace point")
95
+ # TODO test this path
96
+ else
97
+ # If we don't have a component, we cannot log anything properly.
98
+ # Do not just print a warning to avoid spamming customer logs.
99
+ # Don't reraise the exception either.
100
+ # TODO test this path
101
+ end
80
102
  end
81
103
  end
82
104
  end
@@ -112,15 +134,18 @@ module Datadog
112
134
  def iseqs_for_path_suffix(suffix)
113
135
  registry_lock.synchronize do
114
136
  exact = registry[suffix]
115
- return [exact] if exact
137
+ return [suffix, exact] if exact
116
138
 
117
139
  inexact = []
118
140
  registry.each do |path, iseq|
119
141
  if Utils.path_matches_suffix?(path, suffix)
120
- inexact << iseq
142
+ inexact << [path, iseq]
121
143
  end
122
144
  end
123
- inexact
145
+ if inexact.length > 1
146
+ raise Error::MultiplePathsMatch, "Multiple paths matched requested suffix"
147
+ end
148
+ inexact.first
124
149
  end
125
150
  end
126
151
 
@@ -164,3 +189,5 @@ module Datadog
164
189
  end
165
190
  end
166
191
  end
192
+
193
+ # rubocop:enable Lint/AssignmentInCondition
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module DI
5
+ # Component for dynamic instrumentation.
6
+ #
7
+ # Only one instance of the Component should ever be active;
8
+ # if configuration is changed, the old distance should be shut down
9
+ # prior to the new instance being created.
10
+ #
11
+ # The Component instance stores all state related to DI, for example
12
+ # which probes have been retrieved via remote config,
13
+ # intalled tracepoints and so on. Component will clean up all
14
+ # resources and installed tracepoints upon shutdown.
15
+ class Component
16
+ class << self
17
+ def build(settings, agent_settings, telemetry: nil)
18
+ return unless settings.respond_to?(:dynamic_instrumentation) && settings.dynamic_instrumentation.enabled
19
+
20
+ unless settings.respond_to?(:remote) && settings.remote.enabled
21
+ Datadog.logger.debug("Dynamic Instrumentation could not be enabled because Remote Configuration Management is not available. To enable Remote Configuration, see https://docs.datadoghq.com/agent/remote_config")
22
+ return
23
+ end
24
+
25
+ return unless environment_supported?(settings)
26
+
27
+ new(settings, agent_settings, Datadog.logger, code_tracker: DI.code_tracker, telemetry: telemetry)
28
+ end
29
+
30
+ def build!(settings, agent_settings, telemetry: nil)
31
+ unless settings.respond_to?(:dynamic_instrumentation) && settings.dynamic_instrumentation.enabled
32
+ raise "Requested DI component but DI is not enabled in settings"
33
+ end
34
+
35
+ unless settings.respond_to?(:remote) && settings.remote.enabled
36
+ raise "Requested DI component but remote config is not enabled in settings"
37
+ end
38
+
39
+ unless environment_supported?(settings)
40
+ raise "DI does not support the environment (development or Ruby version too low or not MRI)"
41
+ end
42
+
43
+ new(settings, agent_settings, Datadog.logger, code_tracker: DI.code_tracker, telemetry: telemetry)
44
+ end
45
+
46
+ # Checks whether the runtime environment is supported by
47
+ # dynamic instrumentation. Currently we only require that, if Rails
48
+ # is used, that Rails environment is not development because
49
+ # DI does not currently support code unloading and reloading.
50
+ def environment_supported?(settings)
51
+ # TODO add tests?
52
+ unless settings.dynamic_instrumentation.internal.development
53
+ if Datadog::Core::Environment::Execution.development?
54
+ Datadog.logger.debug("Not enabling dynamic instrumentation because we are in development environment")
55
+ return false
56
+ end
57
+ end
58
+ if RUBY_ENGINE != 'ruby' || RUBY_VERSION < '2.6'
59
+ Datadog.logger.debug("Not enabling dynamic instrumentation because of unsupported Ruby version")
60
+ return false
61
+ end
62
+ true
63
+ end
64
+ end
65
+
66
+ def initialize(settings, agent_settings, logger, code_tracker: nil, telemetry: nil)
67
+ @settings = settings
68
+ @agent_settings = agent_settings
69
+ @logger = logger
70
+ @telemetry = telemetry
71
+ @redactor = Redactor.new(settings)
72
+ @serializer = Serializer.new(settings, redactor, telemetry: telemetry)
73
+ @instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry)
74
+ @transport = Transport.new(agent_settings)
75
+ @probe_notifier_worker = ProbeNotifierWorker.new(settings, transport, logger, telemetry: telemetry)
76
+ @probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer)
77
+ @probe_manager = ProbeManager.new(settings, instrumenter, probe_notification_builder, probe_notifier_worker, logger, telemetry: telemetry)
78
+ probe_notifier_worker.start
79
+ end
80
+
81
+ attr_reader :settings
82
+ attr_reader :agent_settings
83
+ attr_reader :logger
84
+ attr_reader :telemetry
85
+ attr_reader :instrumenter
86
+ attr_reader :transport
87
+ attr_reader :probe_notifier_worker
88
+ attr_reader :probe_notification_builder
89
+ attr_reader :probe_manager
90
+ attr_reader :redactor
91
+ attr_reader :serializer
92
+
93
+ # Shuts down dynamic instrumentation.
94
+ #
95
+ # Removes all code hooks and stops background threads.
96
+ #
97
+ # Does not clear out the code tracker, because it's only populated
98
+ # by code when code is compiled and therefore, if the code tracker
99
+ # was replaced by a new instance, the new instance of it wouldn't have
100
+ # any of the already loaded code tracked.
101
+ def shutdown!(replacement = nil)
102
+ probe_manager.clear_hooks
103
+ probe_manager.close
104
+ probe_notifier_worker.stop
105
+ end
106
+ end
107
+ end
108
+ end
@@ -12,8 +12,6 @@ module Datadog
12
12
 
13
13
  def self.add_settings!(base)
14
14
  base.class_eval do
15
- # The setting has "internal" prefix to prevent it from being
16
- # prematurely turned on by customers.
17
15
  settings :dynamic_instrumentation do
18
16
  option :enabled do |o|
19
17
  o.type :bool
@@ -26,48 +24,6 @@ module Datadog
26
24
  o.default false
27
25
  end
28
26
 
29
- # This option instructs dynamic instrumentation to use
30
- # untargeted trace points when installing line probes and
31
- # code tracking is not active.
32
- # WARNING: untargeted trace points carry a massive performance
33
- # penalty for the entire file in which a line probe is placed.
34
- #
35
- # If this option is set to false, which is the default,
36
- # dynamic instrumentation will add probes that reference
37
- # unknown files to the list of pending probes, and when
38
- # the respective files are loaded, the line probes will be
39
- # installed using targeted trace points. If the file in
40
- # question is already loaded when the probe is received
41
- # (for example, it is in a third-party library loaded during
42
- # application boot), and code tracking was not active when
43
- # the file was loaded, such files will not be instrumentable
44
- # via line probes.
45
- #
46
- # If this option is set to true
47
- #
48
- # activated, DI will in
49
- # activated or because the files being targeted have beenIf true and code tracking is not enabled, dynamic instrumentation
50
- # will use untargeted trace points.
51
- # If false and code tracking is not enabled, dynamic
52
- # instrumentation will not instrument any files loaded
53
- # WARNING: these trace points will greatly degrade performance
54
- # of all code in the instrumented files.
55
- option :untargeted_trace_points do |o|
56
- o.type :bool
57
- o.default false
58
- end
59
-
60
- # If true, all of the catch-all rescue blocks in DI
61
- # will propagate the exceptions onward.
62
- # WARNING: for internal Datadog use only - this will break
63
- # the DI product and potentially the library in general in
64
- # a multitude of ways, cause resource leakage, permanent
65
- # performance decreases, etc.
66
- option :propagate_all_exceptions do |o|
67
- o.type :bool
68
- o.default false
69
- end
70
-
71
27
  # An array of variable and key names to redact in addition to
72
28
  # the built-in list of identifiers.
73
29
  #
@@ -154,6 +110,75 @@ module Datadog
154
110
  o.type :int
155
111
  o.default 20
156
112
  end
113
+
114
+ # Settings in the 'internal' group are for internal Datadog
115
+ # use only, and are needed to test dynamic instrumentation or
116
+ # experiment with features not released to customers.
117
+ settings :internal do
118
+ # This option instructs dynamic instrumentation to use
119
+ # untargeted trace points when installing line probes and
120
+ # code tracking is not active.
121
+ # WARNING: untargeted trace points carry a massive performance
122
+ # penalty for the entire file in which a line probe is placed.
123
+ #
124
+ # If this option is set to false, which is the default,
125
+ # dynamic instrumentation will add probes that reference
126
+ # unknown files to the list of pending probes, and when
127
+ # the respective files are loaded, the line probes will be
128
+ # installed using targeted trace points. If the file in
129
+ # question is already loaded when the probe is received
130
+ # (for example, it is in a third-party library loaded during
131
+ # application boot), and code tracking was not active when
132
+ # the file was loaded, such files will not be instrumentable
133
+ # via line probes.
134
+ #
135
+ # If this option is set to true, dynamic instrumentation will
136
+ # install untargeted trace points for all line probes,
137
+ # regardless of whether the referenced file is loaded.
138
+ # This permits instrumenting code which was loaded prior to
139
+ # code tracking being activated and instrumenting lines when
140
+ # code tracking is not activated at all. However, untargeted
141
+ # trace points are extremely slow and will greatly degrade
142
+ # performance of *all* code executed while they are installed,
143
+ # not just the instrumentation target.
144
+ option :untargeted_trace_points do |o|
145
+ o.type :bool
146
+ o.default false
147
+ end
148
+
149
+ # If true, all of the catch-all rescue blocks in DI
150
+ # will propagate the exceptions onward.
151
+ # WARNING: for internal Datadog use only - this will break
152
+ # the DI product and potentially the library in general in
153
+ # a multitude of ways, cause resource leakage, permanent
154
+ # performance decreases, etc.
155
+ option :propagate_all_exceptions do |o|
156
+ o.type :bool
157
+ o.default false
158
+ end
159
+
160
+ # Minimum interval, in seconds, between probe status and
161
+ # snapshot submissions to the agent. Probe notifier worker will
162
+ # batch together payloads submitted during each interval.
163
+ # A longer interval reduces the overhead imposed by dynamic
164
+ # instrumentation on the application, but also increases the
165
+ # time when application code cannot run (when the batches are
166
+ # being sent out by the probe notifier worker) and creates a
167
+ # possibility of dropping payloads if the queue gets too long.
168
+ option :min_send_interval do |o|
169
+ o.type :int
170
+ o.default 3
171
+ end
172
+
173
+ # Enable dynamic instrumentation in development environments.
174
+ # Currently DI does not fully implement support for code
175
+ # unloading and reloading, and is not supported in
176
+ # non-production environments.
177
+ option :development do |o|
178
+ o.type :bool
179
+ o.default false
180
+ end
181
+ end
157
182
  end
158
183
  end
159
184
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Datadog::DI::Serializer.register(condition: lambda { |value| ActiveRecord::Base === value }) do |serializer, value, name:, depth:| # steep:ignore
4
+ # steep thinks all of the arguments are nil here
5
+ # steep:ignore:start
6
+ value_to_serialize = {
7
+ attributes: value.attributes,
8
+ }
9
+ serializer.serialize_value(value_to_serialize, depth: depth ? depth - 1 : nil, type: value.class)
10
+ # steep:ignore:end
11
+ end
@@ -26,6 +26,23 @@ module Datadog
26
26
  # that does not in fact exist anywhere (e.g. due to a misspelling).
27
27
  class DITargetNotDefined < Error
28
28
  end
29
+
30
+ # Raised when trying to install a probe whose installation failed
31
+ # earlier in the same process. This exception should contain the
32
+ # original exception report from initial installation attempt.
33
+ class ProbePreviouslyFailed < Error
34
+ end
35
+
36
+ # Raised when installing a line probe and multiple files match the
37
+ # specified path suffix.
38
+ # A probe must be installed into one file only, since UI only
39
+ # supports one instrumented location for a probe.
40
+ # If multiple files match, UI cannot properly render the data from
41
+ # all of them, and arbitrarily choosing one file may be not what the
42
+ # user intended. Instrumentation will fail when multiple files match
43
+ # and the user will need to make their suffix more precise.
44
+ class MultiplePathsMatch < Error
45
+ end
29
46
  end
30
47
  end
31
48
  end