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 +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
|