datadog 2.6.0 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +3 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +2 -8
- data/ext/datadog_profiling_native_extension/profiling.c +6 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +14 -4
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -0
- data/ext/libdatadog_api/crashtracker.c +6 -4
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +4 -4
- data/lib/datadog/di/code_tracker.rb +30 -3
- data/lib/datadog/di/component.rb +108 -0
- data/lib/datadog/di/configuration/settings.rb +69 -44
- data/lib/datadog/di/contrib/active_record.rb +11 -0
- data/lib/datadog/di/error.rb +17 -0
- data/lib/datadog/di/instrumenter.rb +27 -11
- data/lib/datadog/di/probe.rb +23 -1
- data/lib/datadog/di/probe_manager.rb +246 -0
- data/lib/datadog/di/probe_notification_builder.rb +4 -12
- data/lib/datadog/di/probe_notifier_worker.rb +68 -41
- data/lib/datadog/di/serializer.rb +143 -95
- data/lib/datadog/di/transport.rb +23 -9
- data/lib/datadog/di.rb +49 -1
- data/lib/datadog/tracing/tracer.rb +1 -1
- data/lib/datadog/version.rb +2 -2
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '00617590b3381113b74dde6671802aad74e6ffee0a96737fbc04149515c6a79d'
|
4
|
+
data.tar.gz: 5bed675aca238d308051ba0a728209e2a4a5ba17f2dc11a52eacee8aaf55a123
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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:
|
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
|
-
//
|
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
|
-
|
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)",
|
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)",
|
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
|
61
|
+
// @ivoanjo: The Ruby VM already uses an alt stack to detect stack overflows.
|
62
62
|
//
|
63
|
-
//
|
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,
|
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.
|
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
|
521
|
+
# Only has effect when used together with `gc_enabled: true` and `experimental_heap_enabled: true`.
|
522
522
|
#
|
523
|
-
# @default
|
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
|
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
|
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
|
data/lib/datadog/di/error.rb
CHANGED
@@ -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
|