datadog 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -1
- data/ext/datadog_profiling_loader/extconf.rb +15 -15
- data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +132 -44
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +90 -37
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +69 -62
- data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
- data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/helpers.h +6 -17
- data/ext/datadog_profiling_native_extension/http_transport.c +3 -3
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -126
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
- data/ext/datadog_profiling_native_extension/profiling.c +0 -2
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +27 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
- data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
- data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +20 -7
- data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
- data/ext/libdatadog_api/extconf.rb +108 -0
- data/ext/libdatadog_api/macos_development.md +26 -0
- data/ext/libdatadog_extconf_helpers.rb +130 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +1 -0
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +17 -12
- data/lib/datadog/core/configuration/settings.rb +93 -7
- data/lib/datadog/core/configuration.rb +3 -17
- data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
- data/lib/datadog/core/crashtracking/component.rb +111 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
- data/lib/datadog/core/deprecations.rb +58 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +6 -0
- data/lib/datadog/core/telemetry/component.rb +154 -0
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +132 -26
- data/lib/datadog/core/telemetry/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +11 -13
- data/lib/datadog/core/telemetry/http/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/transport.rb +38 -9
- data/lib/datadog/core/telemetry/logging.rb +35 -0
- data/lib/datadog/core/telemetry/metric.rb +167 -0
- data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
- data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
- data/lib/datadog/core/telemetry/request.rb +1 -1
- data/lib/datadog/core/telemetry/worker.rb +173 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/only_once_successful.rb +76 -0
- data/lib/datadog/core.rb +2 -19
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +24 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +3 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
- data/lib/datadog/profiling/component.rb +85 -90
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +8 -6
- data/lib/datadog/profiling/load_native_extension.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +5 -8
- data/lib/datadog/profiling/scheduler.rb +31 -25
- data/lib/datadog/profiling/tag_builder.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +5 -5
- data/lib/datadog/profiling/tasks/setup.rb +16 -35
- data/lib/datadog/profiling.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -1
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
- data/lib/datadog/tracing/contrib/analytics.rb +5 -0
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
- data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
- data/lib/datadog/tracing/distributed/datadog.rb +2 -2
- data/lib/datadog/tracing/distributed/propagation.rb +9 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +3 -2
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/span.rb +9 -2
- data/lib/datadog/tracing/span_event.rb +41 -0
- data/lib/datadog/tracing/span_operation.rb +9 -4
- data/lib/datadog/tracing/trace_operation.rb +7 -3
- data/lib/datadog/tracing/trace_segment.rb +4 -1
- data/lib/datadog/tracing/tracer.rb +9 -2
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing.rb +5 -1
- data/lib/datadog/version.rb +2 -2
- metadata +43 -12
- data/lib/datadog/core/telemetry/client.rb +0 -95
- data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -1,77 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rubygems'
|
4
|
-
require 'pathname'
|
5
|
-
|
6
3
|
module Datadog
|
7
4
|
module Profiling
|
8
5
|
# Helpers for extconf.rb
|
9
6
|
module NativeExtensionHelpers
|
10
7
|
# Can be set when customers want to skip compiling the native extension entirely
|
11
|
-
ENV_NO_EXTENSION =
|
8
|
+
ENV_NO_EXTENSION = "DD_PROFILING_NO_EXTENSION"
|
12
9
|
# Can be set to force rubygems to fail gem installation when profiling extension could not be built
|
13
|
-
ENV_FAIL_INSTALL_IF_MISSING_EXTENSION =
|
10
|
+
ENV_FAIL_INSTALL_IF_MISSING_EXTENSION = "DD_PROFILING_FAIL_INSTALL_IF_MISSING_EXTENSION"
|
14
11
|
|
15
12
|
# The MJIT header was introduced on 2.6 and removed on 3.3; for other Rubies we rely on debase-ruby_core_source
|
16
|
-
CAN_USE_MJIT_HEADER = RUBY_VERSION.start_with?(
|
17
|
-
|
18
|
-
LIBDATADOG_VERSION = '~> 9.0.0.1.0'
|
13
|
+
CAN_USE_MJIT_HEADER = RUBY_VERSION.start_with?("2.6", "2.7", "3.0.", "3.1.", "3.2.")
|
19
14
|
|
20
15
|
def self.fail_install_if_missing_extension?
|
21
|
-
ENV[ENV_FAIL_INSTALL_IF_MISSING_EXTENSION].to_s.strip.downcase ==
|
22
|
-
end
|
23
|
-
|
24
|
-
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
25
|
-
# libdatadog are moved after the extension gets compiled.
|
26
|
-
#
|
27
|
-
# Because the libddpprof native library is installed on a non-standard system path, in order for it to be
|
28
|
-
# found by the system dynamic linker (e.g. what takes care of dlopen(), which is used to load the profiling
|
29
|
-
# native extension), we need to add a "runpath" -- a list of folders to search for libdatadog.
|
30
|
-
#
|
31
|
-
# This runpath gets hardcoded at native library linking time. You can look at it using the `readelf` tool in
|
32
|
-
# Linux: e.g. `readelf -d datadog_profiling_native_extension.2.7.3_x86_64-linux.so`.
|
33
|
-
#
|
34
|
-
# In older versions of the datadog gem, we only set as runpath an absolute path to libdatadog.
|
35
|
-
# (This gets set automatically by the call
|
36
|
-
# to `pkg_config('datadog_profiling_with_rpath')` in `extconf.rb`). This worked fine as long as libdatadog was **NOT**
|
37
|
-
# moved from the folder it was present at datadog gem installation/linking time.
|
38
|
-
#
|
39
|
-
# Unfortunately, environments such as Heroku and AWS Elastic Beanstalk move gems around in the filesystem after
|
40
|
-
# installation. Thus, the profiling native extension could not be loaded in these environments
|
41
|
-
# (see https://github.com/DataDog/dd-trace-rb/issues/2067) because libdatadog could not be found.
|
42
|
-
#
|
43
|
-
# To workaround this issue, this method computes the **relative** path between the folder where the profiling
|
44
|
-
# native extension is going to be installed and the folder where libdatadog is installed, and returns it
|
45
|
-
# to be set as an additional runpath. (Yes, you can set multiple runpath folders to be searched).
|
46
|
-
#
|
47
|
-
# This way, if both gems are moved together (and it turns out that they are in these environments),
|
48
|
-
# the relative path can still be traversed to find libdatadog.
|
49
|
-
#
|
50
|
-
# This is incredibly awful, and it's kinda bizarre how it's not possible to just find these paths at runtime
|
51
|
-
# and set them correctly; rather than needing to set stuff at linking-time and then praying to $deity that
|
52
|
-
# weird moves don't happen.
|
53
|
-
#
|
54
|
-
# As a curiosity, `LD_LIBRARY_PATH` can be used to influence the folders that get searched but **CANNOT BE
|
55
|
-
# SET DYNAMICALLY**, e.g. it needs to be set at the start of the process (Ruby VM) and thus it's not something
|
56
|
-
# we could setup when doing a `require`.
|
57
|
-
#
|
58
|
-
def self.libdatadog_folder_relative_to_native_lib_folder(
|
59
|
-
current_folder: __dir__,
|
60
|
-
libdatadog_pkgconfig_folder: Libdatadog.pkgconfig_folder
|
61
|
-
)
|
62
|
-
return unless libdatadog_pkgconfig_folder
|
63
|
-
|
64
|
-
profiling_native_lib_folder = "#{current_folder}/../../lib/"
|
65
|
-
libdatadog_lib_folder = "#{libdatadog_pkgconfig_folder}/../"
|
66
|
-
|
67
|
-
Pathname.new(libdatadog_lib_folder).relative_path_from(Pathname.new(profiling_native_lib_folder)).to_s
|
16
|
+
ENV[ENV_FAIL_INSTALL_IF_MISSING_EXTENSION].to_s.strip.downcase == "true"
|
68
17
|
end
|
69
18
|
|
70
19
|
# Used to check if profiler is supported, including user-visible clear messages explaining why their
|
71
20
|
# system may not be supported.
|
72
21
|
module Supported
|
73
22
|
private_class_method def self.explain_issue(*reason, suggested:)
|
74
|
-
{
|
23
|
+
{reason: reason, suggested: suggested}
|
75
24
|
end
|
76
25
|
|
77
26
|
def self.supported?
|
@@ -97,16 +46,16 @@ module Datadog
|
|
97
46
|
outcome =
|
98
47
|
if fail_install
|
99
48
|
[
|
100
|
-
|
49
|
+
"Failing installation immediately because the ",
|
101
50
|
"`#{ENV_FAIL_INSTALL_IF_MISSING_EXTENSION}` environment variable is set",
|
102
|
-
|
103
|
-
|
104
|
-
|
51
|
+
"to `true`.",
|
52
|
+
"When contacting support, please include the <mkmf.log> file that is shown ",
|
53
|
+
"below.",
|
105
54
|
]
|
106
55
|
else
|
107
56
|
[
|
108
|
-
|
109
|
-
|
57
|
+
"The Datadog Continuous Profiler will not be available,",
|
58
|
+
"but all other datadog features will work fine!",
|
110
59
|
]
|
111
60
|
end
|
112
61
|
|
@@ -124,22 +73,14 @@ module Datadog
|
|
124
73
|
|
125
74
|
# This will be saved in a file to later be presented while operating the gem
|
126
75
|
def self.render_skipped_reason_file(reason:, suggested:)
|
127
|
-
[*reason, *suggested].join(
|
128
|
-
end
|
129
|
-
|
130
|
-
# mkmf sets $PKGCONFIG after the `pkg_config` gets used in extconf.rb. When `pkg_config` is unsuccessful, we use
|
131
|
-
# this helper to decide if we can show more specific error message vs a generic "something went wrong".
|
132
|
-
def self.pkg_config_missing?(command: $PKGCONFIG) # rubocop:disable Style/GlobalVars
|
133
|
-
pkg_config_available = command && xsystem("#{command} --version")
|
134
|
-
|
135
|
-
pkg_config_available != true
|
76
|
+
[*reason, *suggested].join(" ")
|
136
77
|
end
|
137
78
|
|
138
79
|
CONTACT_SUPPORT = [
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
80
|
+
"For help solving this issue, please contact Datadog support at",
|
81
|
+
"<https://docs.datadoghq.com/help/>.",
|
82
|
+
"You can also check out the Continuous Profiler troubleshooting page at",
|
83
|
+
"<https://dtdg.co/ruby-profiler-troubleshooting>."
|
143
84
|
].freeze
|
144
85
|
|
145
86
|
GET_IN_TOUCH = [
|
@@ -147,83 +88,83 @@ module Datadog
|
|
147
88
|
].freeze
|
148
89
|
|
149
90
|
UPGRADE_RUBY = [
|
150
|
-
|
91
|
+
"Upgrade to a modern Ruby to enable profiling for your app."
|
151
92
|
].freeze
|
152
93
|
|
153
94
|
# Validation for this check is done in extconf.rb because it relies on mkmf
|
154
95
|
FAILED_TO_CONFIGURE_LIBDATADOG = explain_issue(
|
155
|
-
|
96
|
+
"there was a problem in setting up the `libdatadog` dependency.",
|
156
97
|
suggested: CONTACT_SUPPORT,
|
157
98
|
)
|
158
99
|
|
159
100
|
# Validation for this check is done in extconf.rb because it relies on mkmf
|
160
101
|
COMPILATION_BROKEN = explain_issue(
|
161
|
-
|
162
|
-
|
102
|
+
"compilation of the Ruby VM just-in-time header failed.",
|
103
|
+
"Your C compiler or Ruby VM just-in-time compiler seem to be broken.",
|
163
104
|
suggested: CONTACT_SUPPORT,
|
164
105
|
)
|
165
106
|
|
166
107
|
# Validation for this check is done in extconf.rb because it relies on mkmf
|
167
108
|
PKG_CONFIG_IS_MISSING = explain_issue(
|
168
109
|
# ----------------------------------------------------------------------------+
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
110
|
+
"the `pkg-config` system tool is missing.",
|
111
|
+
"This issue can usually be fixed by installing one of the following:",
|
112
|
+
"the `pkg-config` package on Homebrew and Debian/Ubuntu-based Linux;",
|
113
|
+
"the `pkgconf` package on Arch and Alpine-based Linux;",
|
114
|
+
"the `pkgconf-pkg-config` package on Fedora/Red Hat-based Linux.",
|
115
|
+
"(Tip: When fixing this, ensure `pkg-config` is installed **before**",
|
116
|
+
"running `bundle install`, and remember to clear any installed gems cache).",
|
176
117
|
suggested: CONTACT_SUPPORT,
|
177
118
|
)
|
178
119
|
|
179
120
|
# Validation for this check is done in extconf.rb because it relies on mkmf
|
180
121
|
COMPILER_ATOMIC_MISSING = explain_issue(
|
181
|
-
|
182
|
-
|
183
|
-
|
122
|
+
"your C compiler is missing support for the <stdatomic.h> header.",
|
123
|
+
"This issue can usually be fixed by upgrading to a later version of your",
|
124
|
+
"operating system image or compiler.",
|
184
125
|
suggested: CONTACT_SUPPORT,
|
185
126
|
)
|
186
127
|
|
187
128
|
private_class_method def self.disabled_via_env?
|
188
129
|
report_disabled = [
|
189
|
-
|
190
|
-
|
130
|
+
"If you needed to use this, please tell us why on",
|
131
|
+
"<https://github.com/DataDog/dd-trace-rb/issues/new> so we can fix it :)",
|
191
132
|
].freeze
|
192
133
|
|
193
134
|
disabled_via_env = explain_issue(
|
194
|
-
|
195
|
-
|
135
|
+
"the `DD_PROFILING_NO_EXTENSION` environment variable is/was set to",
|
136
|
+
"`true` during installation.",
|
196
137
|
suggested: report_disabled,
|
197
138
|
)
|
198
139
|
|
199
|
-
return unless ENV[ENV_NO_EXTENSION].to_s.strip.downcase ==
|
140
|
+
return unless ENV[ENV_NO_EXTENSION].to_s.strip.downcase == "true"
|
200
141
|
|
201
142
|
disabled_via_env
|
202
143
|
end
|
203
144
|
|
204
145
|
private_class_method def self.on_jruby?
|
205
146
|
jruby_not_supported = explain_issue(
|
206
|
-
|
147
|
+
"JRuby is not supported by the Datadog Continuous Profiler.",
|
207
148
|
suggested: GET_IN_TOUCH,
|
208
149
|
)
|
209
150
|
|
210
|
-
jruby_not_supported if RUBY_ENGINE ==
|
151
|
+
jruby_not_supported if RUBY_ENGINE == "jruby"
|
211
152
|
end
|
212
153
|
|
213
154
|
private_class_method def self.on_truffleruby?
|
214
155
|
truffleruby_not_supported = explain_issue(
|
215
|
-
|
156
|
+
"TruffleRuby is not supported by the datadog gem.",
|
216
157
|
suggested: GET_IN_TOUCH,
|
217
158
|
)
|
218
159
|
|
219
|
-
truffleruby_not_supported if RUBY_ENGINE ==
|
160
|
+
truffleruby_not_supported if RUBY_ENGINE == "truffleruby"
|
220
161
|
end
|
221
162
|
|
222
163
|
# See https://docs.datadoghq.com/tracing/setup_overview/setup/ruby/#microsoft-windows-support for current
|
223
164
|
# state of Windows support in the datadog gem.
|
224
165
|
private_class_method def self.on_windows?
|
225
166
|
windows_not_supported = explain_issue(
|
226
|
-
|
167
|
+
"Microsoft Windows is not supported by the Datadog Continuous Profiler.",
|
227
168
|
suggested: GET_IN_TOUCH,
|
228
169
|
)
|
229
170
|
|
@@ -232,72 +173,66 @@ module Datadog
|
|
232
173
|
|
233
174
|
private_class_method def self.on_macos?
|
234
175
|
macos_not_supported = explain_issue(
|
235
|
-
|
176
|
+
"macOS is currently not supported by the Datadog Continuous Profiler.",
|
236
177
|
suggested: GET_IN_TOUCH,
|
237
178
|
)
|
238
179
|
# For development only; not supported otherwise
|
239
|
-
macos_testing_override = ENV[
|
180
|
+
macos_testing_override = ENV["DD_PROFILING_MACOS_TESTING"] == "true"
|
240
181
|
|
241
|
-
macos_not_supported if RUBY_PLATFORM.include?(
|
182
|
+
macos_not_supported if RUBY_PLATFORM.include?("darwin") && !macos_testing_override
|
242
183
|
end
|
243
184
|
|
244
185
|
private_class_method def self.on_unknown_os?
|
245
186
|
unknown_os_not_supported = explain_issue(
|
246
|
-
|
187
|
+
"your operating system is not supported by the Datadog Continuous Profiler.",
|
247
188
|
suggested: GET_IN_TOUCH,
|
248
189
|
)
|
249
190
|
|
250
|
-
unknown_os_not_supported unless RUBY_PLATFORM.include?(
|
191
|
+
unknown_os_not_supported unless RUBY_PLATFORM.include?("darwin") || RUBY_PLATFORM.include?("linux")
|
251
192
|
end
|
252
193
|
|
253
194
|
private_class_method def self.on_unsupported_cpu_arch?
|
254
195
|
architecture_not_supported = explain_issue(
|
255
|
-
|
196
|
+
"your CPU architecture is not supported by the Datadog Continuous Profiler.",
|
256
197
|
suggested: GET_IN_TOUCH,
|
257
198
|
)
|
258
199
|
|
259
|
-
architecture_not_supported unless RUBY_PLATFORM.start_with?(
|
200
|
+
architecture_not_supported unless RUBY_PLATFORM.start_with?("x86_64", "aarch64", "arm64")
|
260
201
|
end
|
261
202
|
|
262
203
|
# On some Rubies, we require the mjit header to be present. If Ruby was installed without MJIT support, we also skip
|
263
204
|
# building the extension.
|
264
205
|
private_class_method def self.expected_to_use_mjit_but_mjit_is_disabled?
|
265
206
|
ruby_without_mjit = explain_issue(
|
266
|
-
|
267
|
-
|
268
|
-
|
207
|
+
"your Ruby has been compiled without JIT support (--disable-jit-support).",
|
208
|
+
"The profiling native extension requires a Ruby compiled with JIT support,",
|
209
|
+
"even if the JIT is not in use by the application itself.",
|
269
210
|
suggested: CONTACT_SUPPORT,
|
270
211
|
)
|
271
212
|
|
272
|
-
ruby_without_mjit if CAN_USE_MJIT_HEADER && RbConfig::CONFIG[
|
213
|
+
ruby_without_mjit if CAN_USE_MJIT_HEADER && RbConfig::CONFIG["MJIT_SUPPORT"] != "yes"
|
273
214
|
end
|
274
215
|
|
275
216
|
private_class_method def self.libdatadog_not_available?
|
276
|
-
|
277
|
-
gem 'libdatadog', LIBDATADOG_VERSION
|
278
|
-
require 'libdatadog'
|
279
|
-
nil
|
280
|
-
# rubocop:disable Lint/RescueException
|
281
|
-
rescue Exception => e
|
217
|
+
Datadog::LibdatadogExtconfHelpers.try_loading_libdatadog do |exception|
|
282
218
|
explain_issue(
|
283
|
-
|
284
|
-
|
285
|
-
*
|
286
|
-
*Array(
|
287
|
-
|
219
|
+
"there was an exception during loading of the `libdatadog` gem:",
|
220
|
+
exception.class.name,
|
221
|
+
*exception.message.split("\n"),
|
222
|
+
*Array(exception.backtrace),
|
223
|
+
".",
|
288
224
|
suggested: CONTACT_SUPPORT,
|
289
225
|
)
|
290
226
|
end
|
291
|
-
# rubocop:enable Lint/RescueException
|
292
227
|
end
|
293
228
|
|
294
229
|
private_class_method def self.libdatadog_not_usable?
|
295
230
|
no_binaries_for_current_platform = explain_issue(
|
296
|
-
|
297
|
-
|
231
|
+
"the `libdatadog` gem installed on your system is missing binaries for your",
|
232
|
+
"platform variant.",
|
298
233
|
"(Your platform: `#{Libdatadog.current_platform}`)",
|
299
|
-
|
300
|
-
"`#{Libdatadog.available_binaries.join(
|
234
|
+
"(Available binaries:",
|
235
|
+
"`#{Libdatadog.available_binaries.join("`, `")}`)",
|
301
236
|
suggested: CONTACT_SUPPORT,
|
302
237
|
)
|
303
238
|
|
@@ -311,7 +311,7 @@ VALUE thread_name_for(VALUE thread) {
|
|
311
311
|
// with diagnostic stuff. See https://nelkinda.com/blog/suppress-warnings-in-gcc-and-clang/#d11e364 for details.
|
312
312
|
#pragma GCC diagnostic push
|
313
313
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
314
|
-
inline
|
314
|
+
static inline int
|
315
315
|
calc_pos(const rb_iseq_t *iseq, const VALUE *pc, int *lineno, int *node_id)
|
316
316
|
{
|
317
317
|
VM_ASSERT(iseq);
|
@@ -364,7 +364,7 @@ calc_pos(const rb_iseq_t *iseq, const VALUE *pc, int *lineno, int *node_id)
|
|
364
364
|
// Copyright (C) 1993-2012 Yukihiro Matsumoto
|
365
365
|
// to support our custom rb_profile_frames (see below)
|
366
366
|
// Modifications: None
|
367
|
-
inline
|
367
|
+
static inline int
|
368
368
|
calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
|
369
369
|
{
|
370
370
|
int lineno;
|
@@ -376,8 +376,8 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
|
|
376
376
|
// Copyright (C) 1993-2012 Yukihiro Matsumoto
|
377
377
|
// Modifications:
|
378
378
|
// * Renamed rb_profile_frames => ddtrace_rb_profile_frames
|
379
|
-
// * Add thread argument
|
380
|
-
// * Add is_ruby_frame argument
|
379
|
+
// * Add thread argument (this is now upstream, actually!)
|
380
|
+
// * Add frame_flags.is_ruby_frame argument
|
381
381
|
// * Removed `if (lines)` tests -- require/assume that like `buff`, `lines` is always specified
|
382
382
|
// * Skip dummy frame that shows up in main thread
|
383
383
|
// * Add `end_cfp == NULL` and `end_cfp <= cfp` safety checks. These are used in a bunch of places in
|
@@ -392,6 +392,9 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
|
|
392
392
|
// was called from.
|
393
393
|
// * Imported fix from https://github.com/ruby/ruby/pull/7116 to avoid sampling threads that are still being created
|
394
394
|
// * Imported fix from https://github.com/ruby/ruby/pull/8415 to avoid potential crash when using YJIT.
|
395
|
+
// * Add frame_flags.same_frame and logic to skip redoing work if the buffer already contains the same data we're collecting
|
396
|
+
// * Skipped use of rb_callable_method_entry_t (cme) for Ruby frames as it doesn't impact us.
|
397
|
+
// * Imported fix from https://github.com/ruby/ruby/pull/8280 to keep us closer to upstream
|
395
398
|
//
|
396
399
|
// What is rb_profile_frames?
|
397
400
|
// `rb_profile_frames` is a Ruby VM debug API added for use by profilers for sampling the stack trace of a Ruby thread.
|
@@ -421,8 +424,7 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
|
|
421
424
|
// and friends). We've found quite a few situations where the data from rb_profile_frames and the reference APIs
|
422
425
|
// disagree, and quite a few of them seem oversights/bugs (speculation from my part) rather than deliberate
|
423
426
|
// decisions.
|
424
|
-
int ddtrace_rb_profile_frames(VALUE thread, int start, int limit,
|
425
|
-
{
|
427
|
+
int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *stack_buffer) {
|
426
428
|
int i;
|
427
429
|
// Modified from upstream: Instead of using `GET_EC` to collect info from the current thread,
|
428
430
|
// support sampling any thread (including the current) passed as an argument
|
@@ -466,7 +468,7 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, VALUE *buff, i
|
|
466
468
|
// See comment on `record_placeholder_stack_in_native_code` for a full explanation of what this means (and why we don't just return 0)
|
467
469
|
if (end_cfp <= cfp) return PLACEHOLDER_STACK_IN_NATIVE_CODE;
|
468
470
|
|
469
|
-
for (i=0; i<limit && cfp != end_cfp;) {
|
471
|
+
for (i=0; i<limit && cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
|
470
472
|
if (cfp->iseq && !cfp->pc) {
|
471
473
|
// Fix: Do nothing -- this frame should not be used
|
472
474
|
//
|
@@ -479,164 +481,88 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, VALUE *buff, i
|
|
479
481
|
continue;
|
480
482
|
}
|
481
483
|
|
482
|
-
|
483
|
-
|
484
|
+
stack_buffer[i].same_frame =
|
485
|
+
stack_buffer[i].is_ruby_frame &&
|
486
|
+
stack_buffer[i].as.ruby_frame.iseq == (VALUE) cfp->iseq &&
|
487
|
+
stack_buffer[i].as.ruby_frame.caching_pc == cfp->pc;
|
484
488
|
|
485
|
-
if (
|
486
|
-
|
487
|
-
|
488
|
-
// "when sampling an eval/instance eval inside an object" spec.
|
489
|
-
//
|
490
|
-
// Longer note:
|
491
|
-
// When a frame is a ruby frame (VM_FRAME_RUBYFRAME_P above), we can get information about it
|
492
|
-
// by introspecting both the callable method entry, as well as the iseq directly.
|
493
|
-
// Often they match... but sometimes they provide different info (as in the "iseq for an eval" situation
|
494
|
-
// here).
|
495
|
-
// If my reading of vm_backtrace.c is correct, the actual Ruby stack trace API **never** uses the
|
496
|
-
// callable method entry for Ruby frames, but only for VM_METHOD_TYPE_CFUNC (see `backtrace_each` method
|
497
|
-
// on that file).
|
498
|
-
// So... why does `rb_profile_frames` do something different? Is it a bug? Is it because it exposes
|
499
|
-
// more information than the Ruby stack frame API?
|
500
|
-
// As a final note, the `backtracie` gem (https://github.com/ivoanjo/backtracie) can be used to introspect
|
501
|
-
// the full metadata provided by both the callable method entry as well as the iseq, and is really useful
|
502
|
-
// to debug and learn more about these differences.
|
503
|
-
cfp->iseq->body->type != ISEQ_TYPE_EVAL) {
|
504
|
-
buff[i] = (VALUE)cme;
|
505
|
-
}
|
506
|
-
else {
|
507
|
-
buff[i] = (VALUE)cfp->iseq;
|
489
|
+
if (stack_buffer[i].same_frame) { // Nothing to do, buffer already contains this frame
|
490
|
+
i++;
|
491
|
+
continue;
|
508
492
|
}
|
509
493
|
|
494
|
+
// dd-trace-rb NOTE:
|
495
|
+
// Upstream Ruby has code here to retrieve the rb_callable_method_entry_t (cme) and in some cases to use it
|
496
|
+
// instead of the iseq.
|
497
|
+
// In practice, they are usually the same; the difference is that when you have e.g. block, one gets you a
|
498
|
+
// reference to the block, and the other to the method containing the block.
|
499
|
+
// This would be important if we used `rb_profile_frame_label` and wanted the "block in foo" label instead
|
500
|
+
// of just "foo". But we're currently using `rb_profile_frame_base_label` which I believe is always the same
|
501
|
+
// between the rb_callable_method_entry_t and the iseq. Thus, to simplify a bit our logic and reduce a bit
|
502
|
+
// the overhead, we always use the iseq here.
|
503
|
+
//
|
504
|
+
// @ivoanjo: I've left the upstream Ruby code commented out below for reference, so it's more obvious that
|
505
|
+
// we're diverging, and we can easily compare and experiment with the upstream version in the future.
|
506
|
+
//
|
507
|
+
// cme = rb_vm_frame_method_entry(cfp);
|
508
|
+
|
509
|
+
// if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ &&
|
510
|
+
// // Fix: Do not use callable method entry when iseq is for an eval.
|
511
|
+
// // TL;DR: This fix is needed for us to match the Ruby reference API information in the
|
512
|
+
// // "when sampling an eval/instance eval inside an object" spec.
|
513
|
+
// cfp->iseq->body->type != ISEQ_TYPE_EVAL) {
|
514
|
+
// buff[i] = (VALUE)cme;
|
515
|
+
// }
|
516
|
+
// else {
|
517
|
+
stack_buffer[i].as.ruby_frame.iseq = (VALUE)cfp->iseq;
|
518
|
+
stack_buffer[i].as.ruby_frame.caching_pc = (void *) cfp->pc;
|
519
|
+
// }
|
520
|
+
|
510
521
|
// The topmost frame may not have an updated PC because the JIT
|
511
522
|
// may not have set one. The JIT compiler will update the PC
|
512
523
|
// before entering a new function (so that `caller` will work),
|
513
524
|
// so only the topmost frame could possibly have an out of date PC
|
514
525
|
#ifndef NO_JIT_RETURN
|
515
526
|
if (cfp == top && cfp->jit_return) {
|
516
|
-
|
527
|
+
stack_buffer[i].as.ruby_frame.line = 0;
|
517
528
|
} else {
|
518
|
-
|
529
|
+
stack_buffer[i].as.ruby_frame.line = calc_lineno(cfp->iseq, cfp->pc);
|
519
530
|
}
|
520
531
|
#else // Ruby < 3.1
|
521
|
-
|
532
|
+
stack_buffer[i].as.ruby_frame.line = calc_lineno(cfp->iseq, cfp->pc);
|
522
533
|
#endif
|
523
534
|
|
524
|
-
|
535
|
+
stack_buffer[i].is_ruby_frame = true;
|
525
536
|
i++;
|
526
537
|
}
|
527
538
|
else {
|
528
539
|
cme = rb_vm_frame_method_entry(cfp);
|
529
540
|
if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) {
|
530
|
-
|
531
|
-
|
532
|
-
|
541
|
+
if (start > 0) {
|
542
|
+
start--;
|
543
|
+
continue;
|
544
|
+
}
|
545
|
+
|
546
|
+
stack_buffer[i].same_frame =
|
547
|
+
!stack_buffer[i].is_ruby_frame &&
|
548
|
+
stack_buffer[i].as.native_frame.caching_cme == (VALUE) cme;
|
549
|
+
|
550
|
+
if (stack_buffer[i].same_frame) { // Nothing to do, buffer already contains this frame
|
551
|
+
i++;
|
552
|
+
continue;
|
553
|
+
}
|
554
|
+
|
555
|
+
stack_buffer[i].as.native_frame.caching_cme = (VALUE)cme;
|
556
|
+
stack_buffer[i].as.native_frame.method_id = cme->def->original_id;
|
557
|
+
stack_buffer[i].is_ruby_frame = false;
|
533
558
|
i++;
|
534
559
|
}
|
535
560
|
}
|
536
|
-
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
537
561
|
}
|
538
562
|
|
539
563
|
return i;
|
540
564
|
}
|
541
565
|
|
542
|
-
#ifdef USE_BACKPORTED_RB_PROFILE_FRAME_METHOD_NAME
|
543
|
-
|
544
|
-
// Taken from upstream vm_backtrace.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
|
545
|
-
// Copyright (C) 1993-2012 Yukihiro Matsumoto
|
546
|
-
// to support our custom rb_profile_frame_method_name (see below)
|
547
|
-
// Modifications: None
|
548
|
-
static VALUE
|
549
|
-
id2str(ID id)
|
550
|
-
{
|
551
|
-
VALUE str = rb_id2str(id);
|
552
|
-
if (!str) return Qnil;
|
553
|
-
return str;
|
554
|
-
}
|
555
|
-
#define rb_id2str(id) id2str(id)
|
556
|
-
|
557
|
-
// Taken from upstream vm_backtrace.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
|
558
|
-
// Copyright (C) 1993-2012 Yukihiro Matsumoto
|
559
|
-
// to support our custom rb_profile_frame_method_name (see below)
|
560
|
-
// Modifications: None
|
561
|
-
static const rb_iseq_t *
|
562
|
-
frame2iseq(VALUE frame)
|
563
|
-
{
|
564
|
-
if (NIL_P(frame)) return NULL;
|
565
|
-
|
566
|
-
if (RB_TYPE_P(frame, T_IMEMO)) {
|
567
|
-
switch (imemo_type(frame)) {
|
568
|
-
case imemo_iseq:
|
569
|
-
return (const rb_iseq_t *)frame;
|
570
|
-
case imemo_ment:
|
571
|
-
{
|
572
|
-
const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
|
573
|
-
switch (cme->def->type) {
|
574
|
-
case VM_METHOD_TYPE_ISEQ:
|
575
|
-
return cme->def->body.iseq.iseqptr;
|
576
|
-
default:
|
577
|
-
return NULL;
|
578
|
-
}
|
579
|
-
}
|
580
|
-
default:
|
581
|
-
break;
|
582
|
-
}
|
583
|
-
}
|
584
|
-
rb_bug("frame2iseq: unreachable");
|
585
|
-
}
|
586
|
-
|
587
|
-
// Taken from upstream vm_backtrace.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
|
588
|
-
// Copyright (C) 1993-2012 Yukihiro Matsumoto
|
589
|
-
// to support our custom rb_profile_frame_method_name (see below)
|
590
|
-
// Modifications: None
|
591
|
-
static const rb_callable_method_entry_t *
|
592
|
-
cframe(VALUE frame)
|
593
|
-
{
|
594
|
-
if (NIL_P(frame)) return NULL;
|
595
|
-
|
596
|
-
if (RB_TYPE_P(frame, T_IMEMO)) {
|
597
|
-
switch (imemo_type(frame)) {
|
598
|
-
case imemo_ment:
|
599
|
-
{
|
600
|
-
const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
|
601
|
-
switch (cme->def->type) {
|
602
|
-
case VM_METHOD_TYPE_CFUNC:
|
603
|
-
return cme;
|
604
|
-
default:
|
605
|
-
return NULL;
|
606
|
-
}
|
607
|
-
}
|
608
|
-
default:
|
609
|
-
return NULL;
|
610
|
-
}
|
611
|
-
}
|
612
|
-
|
613
|
-
return NULL;
|
614
|
-
}
|
615
|
-
|
616
|
-
// Taken from upstream vm_backtrace.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
|
617
|
-
// Copyright (C) 1993-2012 Yukihiro Matsumoto
|
618
|
-
//
|
619
|
-
// Ruby 3.0 finally added support for showing CFUNC frames (frames for methods written using native code)
|
620
|
-
// in stack traces gathered via `rb_profile_frames` (https://github.com/ruby/ruby/pull/3299).
|
621
|
-
// To access this information on older Rubies, beyond using our custom `ddtrace_rb_profile_frames` above, we also need
|
622
|
-
// to backport the Ruby 3.0+ version of `rb_profile_frame_method_name`.
|
623
|
-
//
|
624
|
-
// Modifications:
|
625
|
-
// * Renamed rb_profile_frame_method_name => ddtrace_rb_profile_frame_method_name
|
626
|
-
VALUE
|
627
|
-
ddtrace_rb_profile_frame_method_name(VALUE frame)
|
628
|
-
{
|
629
|
-
const rb_callable_method_entry_t *cme = cframe(frame);
|
630
|
-
if (cme) {
|
631
|
-
ID mid = cme->def->original_id;
|
632
|
-
return id2str(mid);
|
633
|
-
}
|
634
|
-
const rb_iseq_t *iseq = frame2iseq(frame);
|
635
|
-
return iseq ? rb_iseq_method_name(iseq) : Qnil;
|
636
|
-
}
|
637
|
-
|
638
|
-
#endif // USE_BACKPORTED_RB_PROFILE_FRAME_METHOD_NAME
|
639
|
-
|
640
566
|
// Support code for older Rubies that cannot use the MJIT header
|
641
567
|
#ifndef RUBY_MJIT_HEADER
|
642
568
|
|
@@ -18,6 +18,22 @@ typedef struct {
|
|
18
18
|
rb_nativethread_id_t owner;
|
19
19
|
} current_gvl_owner;
|
20
20
|
|
21
|
+
typedef struct frame_info {
|
22
|
+
union {
|
23
|
+
struct {
|
24
|
+
VALUE iseq;
|
25
|
+
void *caching_pc; // For caching only
|
26
|
+
int line;
|
27
|
+
} ruby_frame;
|
28
|
+
struct {
|
29
|
+
VALUE caching_cme; // For caching only
|
30
|
+
ID method_id;
|
31
|
+
} native_frame;
|
32
|
+
} as;
|
33
|
+
bool is_ruby_frame : 1;
|
34
|
+
bool same_frame : 1;
|
35
|
+
} frame_info;
|
36
|
+
|
21
37
|
rb_nativethread_id_t pthread_id_for(VALUE thread);
|
22
38
|
bool is_current_thread_holding_the_gvl(void);
|
23
39
|
current_gvl_owner gvl_owner(void);
|
@@ -27,20 +43,10 @@ void ddtrace_thread_list(VALUE result_array);
|
|
27
43
|
bool is_thread_alive(VALUE thread);
|
28
44
|
VALUE thread_name_for(VALUE thread);
|
29
45
|
|
30
|
-
int ddtrace_rb_profile_frames(VALUE thread, int start, int limit,
|
46
|
+
int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *stack_buffer);
|
31
47
|
// Returns true if the current thread belongs to the main Ractor or if Ruby has no Ractor support
|
32
48
|
bool ddtrace_rb_ractor_main_p(void);
|
33
49
|
|
34
|
-
// Ruby 3.0 finally added support for showing CFUNC frames (frames for methods written using native code)
|
35
|
-
// in stack traces gathered via `rb_profile_frames` (https://github.com/ruby/ruby/pull/3299).
|
36
|
-
// To access this information on older Rubies, beyond using our custom `ddtrace_rb_profile_frames` above, we also need
|
37
|
-
// to backport the Ruby 3.0+ version of `rb_profile_frame_method_name`.
|
38
|
-
#ifdef USE_BACKPORTED_RB_PROFILE_FRAME_METHOD_NAME
|
39
|
-
VALUE ddtrace_rb_profile_frame_method_name(VALUE frame);
|
40
|
-
#else // Ruby > 3.0, just use the stock functionality
|
41
|
-
#define ddtrace_rb_profile_frame_method_name rb_profile_frame_method_name
|
42
|
-
#endif
|
43
|
-
|
44
50
|
// See comment on `record_placeholder_stack_in_native_code` for a full explanation of what this means (and why we don't just return 0)
|
45
51
|
#define PLACEHOLDER_STACK_IN_NATIVE_CODE -1
|
46
52
|
|