datadog 2.2.0 → 2.4.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 +87 -2
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +14 -26
- 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 +257 -69
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +53 -28
- 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 +136 -81
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +661 -48
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +83 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +53 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +91 -69
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +54 -12
- 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 +41 -9
- 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 -172
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +116 -139
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +20 -11
- data/ext/datadog_profiling_native_extension/profiling.c +1 -3
- 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.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
- 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 +37 -22
- data/ext/libdatadog_api/datadog_ruby_common.c +83 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +53 -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/assets/waf_rules/recommended.json +2184 -108
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
- data/lib/datadog/appsec/component.rb +29 -8
- data/lib/datadog/appsec/configuration/settings.rb +2 -2
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +35 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +71 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -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 +3 -6
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
- data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
- data/lib/datadog/appsec/processor.rb +36 -37
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +3 -2
- data/lib/datadog/core/configuration/components.rb +18 -15
- data/lib/datadog/core/configuration/settings.rb +135 -9
- 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/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/execution.rb +5 -5
- data/lib/datadog/core/metrics/client.rb +7 -0
- data/lib/datadog/core/rate_limiter.rb +183 -0
- data/lib/datadog/core/remote/client/capabilities.rb +4 -3
- data/lib/datadog/core/remote/component.rb +4 -2
- data/lib/datadog/core/remote/negotiation.rb +4 -4
- data/lib/datadog/core/remote/tie.rb +2 -0
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +51 -2
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +37 -1
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
- 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/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +71 -0
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/di/code_tracker.rb +168 -0
- data/lib/datadog/di/configuration/settings.rb +163 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/error.rb +31 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/probe.rb +133 -0
- data/lib/datadog/di/probe_builder.rb +41 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +193 -0
- data/lib/datadog/di.rb +14 -0
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +28 -26
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +15 -6
- data/lib/datadog/profiling/collectors/thread_context.rb +30 -2
- data/lib/datadog/profiling/component.rb +89 -95
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +14 -7
- 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 +33 -25
- data/lib/datadog/profiling/stack_recorder.rb +3 -0
- 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 +4 -5
- data/lib/datadog/single_step_instrument.rb +12 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +14 -10
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +10 -4
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +15 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -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/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- 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/presto/patcher.rb +1 -13
- 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/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
- 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/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +6 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/remote.rb +5 -2
- data/lib/datadog/tracing/sampling/matcher.rb +6 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +2 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.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 +6 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +14 -12
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +46 -11
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -3,13 +3,22 @@
|
|
3
3
|
#include <ruby.h>
|
4
4
|
#include <stdbool.h>
|
5
5
|
|
6
|
+
#include "gvl_profiling_helper.h"
|
7
|
+
|
6
8
|
void thread_context_collector_sample(
|
7
9
|
VALUE self_instance,
|
8
10
|
long current_monotonic_wall_time_ns,
|
9
11
|
VALUE profiler_overhead_stack_thread
|
10
12
|
);
|
11
13
|
void thread_context_collector_sample_allocation(VALUE self_instance, unsigned int sample_weight, VALUE new_object);
|
14
|
+
void thread_context_collector_sample_skipped_allocation_samples(VALUE self_instance, unsigned int skipped_samples);
|
12
15
|
VALUE thread_context_collector_sample_after_gc(VALUE self_instance);
|
13
16
|
void thread_context_collector_on_gc_start(VALUE self_instance);
|
14
|
-
bool thread_context_collector_on_gc_finish(VALUE self_instance);
|
17
|
+
__attribute__((warn_unused_result)) bool thread_context_collector_on_gc_finish(VALUE self_instance);
|
15
18
|
VALUE enforce_thread_context_collector_instance(VALUE object);
|
19
|
+
|
20
|
+
#ifndef NO_GVL_INSTRUMENTATION
|
21
|
+
void thread_context_collector_on_gvl_waiting(gvl_profiling_thread thread);
|
22
|
+
__attribute__((warn_unused_result)) bool thread_context_collector_on_gvl_running(gvl_profiling_thread thread);
|
23
|
+
VALUE thread_context_collector_sample_after_gvl_running(VALUE self_instance);
|
24
|
+
#endif
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#include "datadog_ruby_common.h"
|
2
|
+
|
3
|
+
// IMPORTANT: Currently this file is copy-pasted between extensions. Make sure to update all versions when doing any change!
|
4
|
+
|
5
|
+
void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name) {
|
6
|
+
rb_exc_raise(
|
7
|
+
rb_exc_new_str(
|
8
|
+
rb_eTypeError,
|
9
|
+
rb_sprintf("wrong argument %"PRIsVALUE" for '%s' (expected a %s) at %s:%d:in `%s'",
|
10
|
+
rb_inspect(value),
|
11
|
+
value_name,
|
12
|
+
type_name,
|
13
|
+
file,
|
14
|
+
line,
|
15
|
+
function_name
|
16
|
+
)
|
17
|
+
)
|
18
|
+
);
|
19
|
+
}
|
20
|
+
|
21
|
+
VALUE datadog_gem_version(void) {
|
22
|
+
VALUE ddtrace_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
|
23
|
+
ENFORCE_TYPE(ddtrace_module, T_MODULE);
|
24
|
+
VALUE version_module = rb_const_get(ddtrace_module, rb_intern("VERSION"));
|
25
|
+
ENFORCE_TYPE(version_module, T_MODULE);
|
26
|
+
VALUE version_string = rb_const_get(version_module, rb_intern("STRING"));
|
27
|
+
ENFORCE_TYPE(version_string, T_STRING);
|
28
|
+
return version_string;
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE log_failure_to_process_tag(VALUE err_details) {
|
32
|
+
VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
|
33
|
+
VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
|
34
|
+
|
35
|
+
return rb_funcall(logger, rb_intern("warn"), 1, rb_sprintf("Failed to convert tag: %"PRIsVALUE, err_details));
|
36
|
+
}
|
37
|
+
|
38
|
+
__attribute__((warn_unused_result))
|
39
|
+
ddog_Vec_Tag convert_tags(VALUE tags_as_array) {
|
40
|
+
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
41
|
+
|
42
|
+
long tags_count = RARRAY_LEN(tags_as_array);
|
43
|
+
ddog_Vec_Tag tags = ddog_Vec_Tag_new();
|
44
|
+
|
45
|
+
for (long i = 0; i < tags_count; i++) {
|
46
|
+
VALUE name_value_pair = rb_ary_entry(tags_as_array, i);
|
47
|
+
|
48
|
+
if (!RB_TYPE_P(name_value_pair, T_ARRAY)) {
|
49
|
+
ddog_Vec_Tag_drop(tags);
|
50
|
+
ENFORCE_TYPE(name_value_pair, T_ARRAY);
|
51
|
+
}
|
52
|
+
|
53
|
+
// Note: We can index the array without checking its size first because rb_ary_entry returns Qnil if out of bounds
|
54
|
+
VALUE tag_name = rb_ary_entry(name_value_pair, 0);
|
55
|
+
VALUE tag_value = rb_ary_entry(name_value_pair, 1);
|
56
|
+
|
57
|
+
if (!(RB_TYPE_P(tag_name, T_STRING) && RB_TYPE_P(tag_value, T_STRING))) {
|
58
|
+
ddog_Vec_Tag_drop(tags);
|
59
|
+
ENFORCE_TYPE(tag_name, T_STRING);
|
60
|
+
ENFORCE_TYPE(tag_value, T_STRING);
|
61
|
+
}
|
62
|
+
|
63
|
+
ddog_Vec_Tag_PushResult push_result =
|
64
|
+
ddog_Vec_Tag_push(&tags, char_slice_from_ruby_string(tag_name), char_slice_from_ruby_string(tag_value));
|
65
|
+
|
66
|
+
if (push_result.tag == DDOG_VEC_TAG_PUSH_RESULT_ERR) {
|
67
|
+
// libdatadog validates tags and may catch invalid tags that ddtrace didn't actually catch.
|
68
|
+
// We warn users about such tags, and then just ignore them.
|
69
|
+
|
70
|
+
int exception_state;
|
71
|
+
rb_protect(log_failure_to_process_tag, get_error_details_and_drop(&push_result.err), &exception_state);
|
72
|
+
|
73
|
+
// Since we are calling into Ruby code, it may raise an exception. Ensure that dynamically-allocated tags
|
74
|
+
// get cleaned before propagating the exception.
|
75
|
+
if (exception_state) {
|
76
|
+
ddog_Vec_Tag_drop(tags);
|
77
|
+
rb_jump_tag(exception_state); // "Re-raise" exception
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
return tags;
|
83
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
// IMPORTANT: Currently this file is copy-pasted between extensions. Make sure to update all versions when doing any change!
|
4
|
+
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <datadog/profiling.h>
|
7
|
+
|
8
|
+
// Used to mark symbols to be exported to the outside of the extension.
|
9
|
+
// Consider very carefully before tagging a function with this.
|
10
|
+
#define DDTRACE_EXPORT __attribute__ ((visibility ("default")))
|
11
|
+
|
12
|
+
// Used to mark function arguments that are deliberately left unused
|
13
|
+
#ifdef __GNUC__
|
14
|
+
#define DDTRACE_UNUSED __attribute__((unused))
|
15
|
+
#else
|
16
|
+
#define DDTRACE_UNUSED
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#define ADD_QUOTES_HELPER(x) #x
|
20
|
+
#define ADD_QUOTES(x) ADD_QUOTES_HELPER(x)
|
21
|
+
|
22
|
+
// Ruby has a Check_Type(value, type) that is roughly equivalent to this BUT Ruby's version is rather cryptic when it fails
|
23
|
+
// e.g. "wrong argument type nil (expected String)". This is a replacement that prints more information to help debugging.
|
24
|
+
#define ENFORCE_TYPE(value, type) \
|
25
|
+
{ if (RB_UNLIKELY(!RB_TYPE_P(value, type))) raise_unexpected_type(value, ADD_QUOTES(value), ADD_QUOTES(type), __FILE__, __LINE__, __func__); }
|
26
|
+
|
27
|
+
#define ENFORCE_BOOLEAN(value) \
|
28
|
+
{ if (RB_UNLIKELY(value != Qtrue && value != Qfalse)) raise_unexpected_type(value, ADD_QUOTES(value), "true or false", __FILE__, __LINE__, __func__); }
|
29
|
+
|
30
|
+
NORETURN(void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name));
|
31
|
+
|
32
|
+
// Helper to retrieve Datadog::VERSION::STRING
|
33
|
+
VALUE datadog_gem_version(void);
|
34
|
+
|
35
|
+
static inline ddog_CharSlice char_slice_from_ruby_string(VALUE string) {
|
36
|
+
ENFORCE_TYPE(string, T_STRING);
|
37
|
+
ddog_CharSlice char_slice = {.ptr = RSTRING_PTR(string), .len = RSTRING_LEN(string)};
|
38
|
+
return char_slice;
|
39
|
+
}
|
40
|
+
|
41
|
+
__attribute__((warn_unused_result))
|
42
|
+
ddog_Vec_Tag convert_tags(VALUE tags_as_array);
|
43
|
+
|
44
|
+
static inline VALUE ruby_string_from_error(const ddog_Error *error) {
|
45
|
+
ddog_CharSlice char_slice = ddog_Error_message(error);
|
46
|
+
return rb_str_new(char_slice.ptr, char_slice.len);
|
47
|
+
}
|
48
|
+
|
49
|
+
static inline VALUE get_error_details_and_drop(ddog_Error *error) {
|
50
|
+
VALUE result = ruby_string_from_error(error);
|
51
|
+
ddog_Error_drop(error);
|
52
|
+
return result;
|
53
|
+
}
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# rubocop:disable Style/StderrPuts
|
2
2
|
# rubocop:disable Style/GlobalVars
|
3
3
|
|
4
|
-
require_relative
|
4
|
+
require_relative "native_extension_helpers"
|
5
|
+
require_relative "../libdatadog_extconf_helpers"
|
5
6
|
|
6
7
|
SKIPPED_REASON_FILE = "#{__dir__}/skipped_reason.txt".freeze
|
7
8
|
# Not a problem if the file doesn't exist or we can't delete it
|
8
|
-
|
9
|
+
begin
|
10
|
+
File.delete(SKIPPED_REASON_FILE)
|
11
|
+
rescue
|
12
|
+
nil
|
13
|
+
end
|
9
14
|
|
10
15
|
def skip_building_extension!(reason)
|
11
16
|
fail_install_if_missing_extension =
|
@@ -24,13 +29,13 @@ def skip_building_extension!(reason)
|
|
24
29
|
)
|
25
30
|
|
26
31
|
if fail_install_if_missing_extension
|
27
|
-
require
|
32
|
+
require "mkmf"
|
28
33
|
Logging.message(
|
29
|
-
|
34
|
+
"[datadog] Failure cause: " \
|
30
35
|
"#{Datadog::Profiling::NativeExtensionHelpers::Supported.render_skipped_reason_file(**reason)}\n"
|
31
36
|
)
|
32
37
|
else
|
33
|
-
File.write(
|
38
|
+
File.write("Makefile", "all install clean: # dummy makefile that does nothing")
|
34
39
|
end
|
35
40
|
|
36
41
|
exit
|
@@ -63,41 +68,31 @@ $stderr.puts(
|
|
63
68
|
|
64
69
|
# NOTE: we MUST NOT require 'mkmf' before we check the #skip_building_extension? because the require triggers checks
|
65
70
|
# that may fail on an environment not properly setup for building Ruby extensions.
|
66
|
-
require
|
71
|
+
require "mkmf"
|
67
72
|
|
68
73
|
Logging.message("[datadog] Using compiler:\n")
|
69
|
-
xsystem("#{CONFIG[
|
74
|
+
xsystem("#{CONFIG["CC"]} -v")
|
70
75
|
Logging.message("[datadog] End of compiler information\n")
|
71
76
|
|
72
|
-
# mkmf on modern Rubies actually has an append_cflags that does something similar
|
73
|
-
# (see https://github.com/ruby/ruby/pull/5760), but as usual we need a bit more boilerplate to deal with legacy Rubies
|
74
|
-
def add_compiler_flag(flag)
|
75
|
-
if try_cflags(flag)
|
76
|
-
$CFLAGS << ' ' << flag
|
77
|
-
else
|
78
|
-
$stderr.puts("WARNING: '#{flag}' not accepted by compiler, skipping it")
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
77
|
# Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
|
83
78
|
# But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
|
84
|
-
|
79
|
+
append_cflags "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
|
85
80
|
|
86
81
|
# Older gcc releases may not default to C99 and we need to ask for this. This is also used:
|
87
82
|
# * by upstream Ruby -- search for gnu99 in the codebase
|
88
83
|
# * by msgpack, another datadog gem dependency
|
89
84
|
# (https://github.com/msgpack/msgpack-ruby/blob/18ce08f6d612fe973843c366ac9a0b74c4e50599/ext/msgpack/extconf.rb#L8)
|
90
|
-
|
85
|
+
append_cflags "-std=gnu99"
|
91
86
|
|
92
87
|
# Gets really noisy when we include the MJIT header, let's omit it (TODO: Use #pragma GCC diagnostic instead?)
|
93
|
-
|
88
|
+
append_cflags "-Wno-unused-function"
|
94
89
|
|
95
90
|
# Allow defining variables at any point in a function
|
96
|
-
|
91
|
+
append_cflags "-Wno-declaration-after-statement"
|
97
92
|
|
98
93
|
# If we forget to include a Ruby header, the function call may still appear to work, but then
|
99
94
|
# cause a segfault later. Let's ensure that never happens.
|
100
|
-
|
95
|
+
append_cflags "-Werror-implicit-function-declaration"
|
101
96
|
|
102
97
|
# The native extension is not intended to expose any symbols/functions for other native libraries to use;
|
103
98
|
# the sole exception being `Init_datadog_profiling_native_extension` which needs to be visible for Ruby to call it when
|
@@ -105,22 +100,22 @@ add_compiler_flag '-Werror-implicit-function-declaration'
|
|
105
100
|
#
|
106
101
|
# By setting this compiler flag, we tell it to assume that everything is private unless explicitly stated.
|
107
102
|
# For more details see https://gcc.gnu.org/wiki/Visibility
|
108
|
-
|
103
|
+
append_cflags "-fvisibility=hidden"
|
109
104
|
|
110
105
|
# Avoid legacy C definitions
|
111
|
-
|
106
|
+
append_cflags "-Wold-style-definition"
|
112
107
|
|
113
108
|
# Enable all other compiler warnings
|
114
|
-
|
115
|
-
|
109
|
+
append_cflags "-Wall"
|
110
|
+
append_cflags "-Wextra"
|
116
111
|
|
117
|
-
if ENV[
|
118
|
-
$defs <<
|
119
|
-
CONFIG[
|
120
|
-
CONFIG[
|
112
|
+
if ENV["DDTRACE_DEBUG"] == "true"
|
113
|
+
$defs << "-DDD_DEBUG"
|
114
|
+
CONFIG["optflags"] = "-O0"
|
115
|
+
CONFIG["debugflags"] = "-ggdb3"
|
121
116
|
end
|
122
117
|
|
123
|
-
if RUBY_PLATFORM.include?(
|
118
|
+
if RUBY_PLATFORM.include?("linux")
|
124
119
|
# Supposedly, the correct way to do this is
|
125
120
|
# ```
|
126
121
|
# have_library 'pthread'
|
@@ -128,77 +123,83 @@ if RUBY_PLATFORM.include?('linux')
|
|
128
123
|
# ```
|
129
124
|
# but it's slower to build
|
130
125
|
# so instead we just assume that we have the function we need on Linux, and nowhere else
|
131
|
-
$defs <<
|
126
|
+
$defs << "-DHAVE_PTHREAD_GETCPUCLOCKID"
|
127
|
+
|
128
|
+
# Not available on macOS
|
129
|
+
$defs << "-DHAVE_CLOCK_MONOTONIC_COARSE"
|
132
130
|
end
|
133
131
|
|
134
|
-
have_func
|
132
|
+
have_func "malloc_stats"
|
135
133
|
|
136
134
|
# On older Rubies, rb_postponed_job_preregister/rb_postponed_job_trigger did not exist
|
137
|
-
$defs <<
|
135
|
+
$defs << "-DNO_POSTPONED_TRIGGER" if RUBY_VERSION < "3.3"
|
138
136
|
|
139
137
|
# On older Rubies, M:N threads were not available
|
140
|
-
$defs <<
|
138
|
+
$defs << "-DNO_MN_THREADS_AVAILABLE" if RUBY_VERSION < "3.3"
|
141
139
|
|
142
140
|
# On older Rubies, we did not need to include the ractor header (this was built into the MJIT header)
|
143
|
-
$defs <<
|
141
|
+
$defs << "-DNO_RACTOR_HEADER_INCLUDE" if RUBY_VERSION < "3.3"
|
144
142
|
|
145
143
|
# On older Rubies, some of the Ractor internal APIs were directly accessible
|
146
|
-
$defs <<
|
144
|
+
$defs << "-DUSE_RACTOR_INTERNAL_APIS_DIRECTLY" if RUBY_VERSION < "3.3"
|
145
|
+
|
146
|
+
# On older Rubies, there was no GVL instrumentation API and APIs created to support it
|
147
|
+
$defs << "-DNO_GVL_INSTRUMENTATION" if RUBY_VERSION < "3.2"
|
148
|
+
|
149
|
+
# Supporting GVL instrumentation on 3.2 needs some workarounds
|
150
|
+
$defs << "-DUSE_GVL_PROFILING_3_2_WORKAROUNDS" if RUBY_VERSION.start_with?("3.2")
|
147
151
|
|
148
152
|
# On older Rubies, there was no struct rb_native_thread. See private_vm_api_acccess.c for details.
|
149
|
-
$defs <<
|
153
|
+
$defs << "-DNO_RB_NATIVE_THREAD" if RUBY_VERSION < "3.2"
|
150
154
|
|
151
155
|
# On older Rubies, there was no struct rb_thread_sched (it was struct rb_global_vm_lock_struct)
|
152
|
-
$defs <<
|
156
|
+
$defs << "-DNO_RB_THREAD_SCHED" if RUBY_VERSION < "3.2"
|
153
157
|
|
154
158
|
# On older Rubies, the first_lineno inside a location was a VALUE and not a int (https://github.com/ruby/ruby/pull/6430)
|
155
|
-
$defs <<
|
159
|
+
$defs << "-DNO_INT_FIRST_LINENO" if RUBY_VERSION < "3.2"
|
156
160
|
|
157
161
|
# On older Rubies, "pop" was not a primitive operation
|
158
|
-
$defs <<
|
162
|
+
$defs << "-DNO_PRIMITIVE_POP" if RUBY_VERSION < "3.2"
|
159
163
|
|
160
164
|
# On older Rubies, there was no tid member in the internal thread structure
|
161
|
-
$defs <<
|
165
|
+
$defs << "-DNO_THREAD_TID" if RUBY_VERSION < "3.1"
|
162
166
|
|
163
167
|
# On older Rubies, there was no jit_return member on the rb_control_frame_t struct
|
164
|
-
$defs <<
|
168
|
+
$defs << "-DNO_JIT_RETURN" if RUBY_VERSION < "3.1"
|
165
169
|
|
166
170
|
# On older Rubies, rb_gc_force_recycle allowed to free objects in a way that
|
167
171
|
# would be invisible to free tracepoints, finalizers and without cleaning
|
168
172
|
# obj_to_id_tbl mappings.
|
169
|
-
$defs <<
|
170
|
-
|
171
|
-
# On older Rubies, we need to use a backported version of this function. See private_vm_api_access.h for details.
|
172
|
-
$defs << '-DUSE_BACKPORTED_RB_PROFILE_FRAME_METHOD_NAME' if RUBY_VERSION < '3'
|
173
|
+
$defs << "-DHAVE_WORKING_RB_GC_FORCE_RECYCLE" if RUBY_VERSION < "3.1"
|
173
174
|
|
174
175
|
# On older Rubies, there are no Ractors
|
175
|
-
$defs <<
|
176
|
+
$defs << "-DNO_RACTORS" if RUBY_VERSION < "3"
|
176
177
|
|
177
178
|
# On older Rubies, rb_imemo_name did not exist
|
178
|
-
$defs <<
|
179
|
+
$defs << "-DNO_IMEMO_NAME" if RUBY_VERSION < "3"
|
179
180
|
|
180
181
|
# On older Rubies, objects would not move
|
181
|
-
$defs <<
|
182
|
+
$defs << "-DNO_T_MOVED" if RUBY_VERSION < "2.7"
|
182
183
|
|
183
184
|
# On older Rubies, there was no RUBY_SEEN_OBJ_ID flag
|
184
|
-
$defs <<
|
185
|
+
$defs << "-DNO_SEEN_OBJ_ID_FLAG" if RUBY_VERSION < "2.7"
|
185
186
|
|
186
187
|
# On older Rubies, rb_global_vm_lock_struct did not include the owner field
|
187
|
-
$defs <<
|
188
|
+
$defs << "-DNO_GVL_OWNER" if RUBY_VERSION < "2.6"
|
188
189
|
|
189
190
|
# On older Rubies, there was no thread->invoke_arg
|
190
|
-
$defs <<
|
191
|
+
$defs << "-DNO_THREAD_INVOKE_ARG" if RUBY_VERSION < "2.6"
|
191
192
|
|
192
193
|
# If we got here, libdatadog is available and loaded
|
193
|
-
ENV[
|
194
|
-
Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV[
|
194
|
+
ENV["PKG_CONFIG_PATH"] = "#{ENV["PKG_CONFIG_PATH"]}:#{Libdatadog.pkgconfig_folder}"
|
195
|
+
Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV["PKG_CONFIG_PATH"].inspect}\n")
|
195
196
|
$stderr.puts("Using libdatadog #{Libdatadog::VERSION} from #{Libdatadog.pkgconfig_folder}")
|
196
197
|
|
197
|
-
unless pkg_config(
|
198
|
+
unless pkg_config("datadog_profiling_with_rpath")
|
198
199
|
Logging.message("[datadog] Ruby detected the pkg-config command is #{$PKGCONFIG.inspect}\n")
|
199
200
|
|
200
201
|
skip_building_extension!(
|
201
|
-
if Datadog::
|
202
|
+
if Datadog::LibdatadogExtconfHelpers.pkg_config_missing?
|
202
203
|
Datadog::Profiling::NativeExtensionHelpers::Supported::PKG_CONFIG_IS_MISSING
|
203
204
|
else
|
204
205
|
# Less specific error message
|
@@ -207,7 +208,7 @@ unless pkg_config('datadog_profiling_with_rpath')
|
|
207
208
|
)
|
208
209
|
end
|
209
210
|
|
210
|
-
unless have_type(
|
211
|
+
unless have_type("atomic_int", ["stdatomic.h"])
|
211
212
|
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
|
212
213
|
end
|
213
214
|
|
@@ -215,8 +216,8 @@ end
|
|
215
216
|
# The extremely excessive escaping around ORIGIN below seems to be correct and was determined after a lot of
|
216
217
|
# experimentation. We need to get these special characters across a lot of tools untouched...
|
217
218
|
extra_relative_rpaths = [
|
218
|
-
Datadog::
|
219
|
-
*Datadog::
|
219
|
+
Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_native_lib_folder(current_folder: __dir__),
|
220
|
+
*Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_ruby_extensions_folders,
|
220
221
|
]
|
221
222
|
extra_relative_rpaths.each { |folder| $LDFLAGS += " -Wl,-rpath,$$$\\\\{ORIGIN\\}/#{folder.to_str}" }
|
222
223
|
Logging.message("[datadog] After pkg-config $LDFLAGS were set to: #{$LDFLAGS.inspect}\n")
|
@@ -237,8 +238,8 @@ if Datadog::Profiling::NativeExtensionHelpers::CAN_USE_MJIT_HEADER
|
|
237
238
|
# use the MJIT header.
|
238
239
|
# Finally, the `COMMON_HEADERS` conflict with the MJIT header so we need to temporarily disable them for this check.
|
239
240
|
original_common_headers = MakeMakefile::COMMON_HEADERS
|
240
|
-
MakeMakefile::COMMON_HEADERS =
|
241
|
-
unless have_macro(
|
241
|
+
MakeMakefile::COMMON_HEADERS = "".freeze
|
242
|
+
unless have_macro("RUBY_MJIT_H", mjit_header_file_name)
|
242
243
|
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILATION_BROKEN)
|
243
244
|
end
|
244
245
|
MakeMakefile::COMMON_HEADERS = original_common_headers
|
@@ -250,7 +251,7 @@ if Datadog::Profiling::NativeExtensionHelpers::CAN_USE_MJIT_HEADER
|
|
250
251
|
|
251
252
|
# Warn on unused parameters to functions. Use `DDTRACE_UNUSED` to mark things as known-to-not-be-used.
|
252
253
|
# See the comment on the same flag below for why this is done last.
|
253
|
-
|
254
|
+
append_cflags "-Wunused-parameter"
|
254
255
|
|
255
256
|
create_makefile EXTENSION_NAME
|
256
257
|
else
|
@@ -261,23 +262,44 @@ else
|
|
261
262
|
|
262
263
|
create_header
|
263
264
|
|
264
|
-
require
|
265
|
-
dir_config(
|
265
|
+
require "debase/ruby_core_source"
|
266
|
+
dir_config("ruby") # allow user to pass in non-standard core include directory
|
267
|
+
|
268
|
+
# This is a workaround for a weird issue...
|
269
|
+
#
|
270
|
+
# The mkmf tool defines a `with_cppflags` helper that debase-ruby_core_source uses. This helper temporarily
|
271
|
+
# replaces `$CPPFLAGS` (aka the C pre-processor [not c++!] flags) with a different set when doing something.
|
272
|
+
#
|
273
|
+
# The debase-ruby_core_source gem uses `with_cppflags` during makefile generation to inject extra headers into the
|
274
|
+
# path. But because `with_cppflags` replaces `$CPPFLAGS`, well, the default `$CPPFLAGS` are not included in the
|
275
|
+
# makefile.
|
276
|
+
#
|
277
|
+
# This is a problem because the default `$CPPFLAGS` carries configuration that was set when Ruby was being built.
|
278
|
+
# Thus, if we ignore it, we don't compile the profiler with the exact same configuration as Ruby.
|
279
|
+
# In practice, this can generate crashes and weird bugs if the Ruby configuration is tweaked in a manner that
|
280
|
+
# changes some of the internal structures that the profiler relies on. Concretely, setting for instance
|
281
|
+
# `VM_CHECK_MODE=1` when building Ruby will trigger this issue (because somethings in structures the profiler reads
|
282
|
+
# are ifdef'd out using this setting).
|
283
|
+
#
|
284
|
+
# To workaround this issue, we override `with_cppflags` for debase-ruby_core_source to still include `$CPPFLAGS`.
|
285
|
+
Debase::RubyCoreSource.define_singleton_method(:with_cppflags) do |newflags, &block|
|
286
|
+
super("#{newflags} #{$CPPFLAGS}", &block)
|
287
|
+
end
|
266
288
|
|
267
289
|
Debase::RubyCoreSource
|
268
290
|
.create_makefile_with_core(
|
269
291
|
proc do
|
270
292
|
headers_available =
|
271
|
-
have_header(
|
272
|
-
have_header(
|
273
|
-
(RUBY_VERSION <
|
293
|
+
have_header("vm_core.h") &&
|
294
|
+
have_header("iseq.h") &&
|
295
|
+
(RUBY_VERSION < "3.3" || have_header("ractor_core.h"))
|
274
296
|
|
275
297
|
if headers_available
|
276
298
|
# Warn on unused parameters to functions. Use `DDTRACE_UNUSED` to mark things as known-to-not-be-used.
|
277
299
|
# This is added as late as possible because in some Rubies we support (e.g. 3.3), adding this flag before
|
278
300
|
# checking if internal VM headers are available causes those checks to fail because of this warning (and not
|
279
301
|
# because the headers are not available.)
|
280
|
-
|
302
|
+
append_cflags "-Wunused-parameter"
|
281
303
|
end
|
282
304
|
|
283
305
|
headers_available
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ruby/thread.h>
|
3
|
+
#include "gvl_profiling_helper.h"
|
4
|
+
|
5
|
+
#if !defined(NO_GVL_INSTRUMENTATION) && !defined(USE_GVL_PROFILING_3_2_WORKAROUNDS) // Ruby 3.3+
|
6
|
+
rb_internal_thread_specific_key_t gvl_waiting_tls_key;
|
7
|
+
|
8
|
+
void gvl_profiling_init(void) {
|
9
|
+
gvl_waiting_tls_key = rb_internal_thread_specific_key_create();
|
10
|
+
}
|
11
|
+
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#ifdef USE_GVL_PROFILING_3_2_WORKAROUNDS // Ruby 3.2
|
15
|
+
__thread gvl_profiling_thread gvl_waiting_tls;
|
16
|
+
static bool gvl_profiling_state_thread_tracking_workaround_installed = false;
|
17
|
+
|
18
|
+
static void on_thread_start(
|
19
|
+
DDTRACE_UNUSED rb_event_flag_t _unused1,
|
20
|
+
DDTRACE_UNUSED const rb_internal_thread_event_data_t *_unused2,
|
21
|
+
DDTRACE_UNUSED void *_unused3
|
22
|
+
) {
|
23
|
+
gvl_waiting_tls = (gvl_profiling_thread) {.thread = NULL};
|
24
|
+
}
|
25
|
+
|
26
|
+
// Hack: We're using the gvl_waiting_tls native thread-local to store per-thread information. Unfortunately, Ruby puts a big hole
|
27
|
+
// in our plan because it reuses native threads -- specifically, in Ruby 3.2, native threads are still 1:1 to Ruby
|
28
|
+
// threads (M:N wasn't a thing yet) BUT once a Ruby thread dies, the VM will keep the native thread around for a
|
29
|
+
// bit, and if another Ruby thread starts right after, Ruby will reuse the native thread, rather than create a new one.
|
30
|
+
//
|
31
|
+
// This will mean that the new Ruby thread will still have the same native thread-local data that we set on the
|
32
|
+
// old thread. For the purposes of our tracking, where we're keeping a pointer to the current thread object in
|
33
|
+
// thread-local storage **this is disastrous** since it means we'll be pointing at the wrong thread (and its
|
34
|
+
// memory may have been freed or reused since!)
|
35
|
+
//
|
36
|
+
// To work around this issue, once GVL profiling is enabled, we install an event hook on thread start
|
37
|
+
// events that clears the thread-local data. This guarantees that there will be no stale data -- any existing
|
38
|
+
// data will be cleared at thread start.
|
39
|
+
//
|
40
|
+
// Note that once installed, this event hook becomes permanent -- stopping the profiler does not stop this event
|
41
|
+
// hook, unlike all others. This is because we can't afford to miss any thread start events while the
|
42
|
+
// profiler is stopped (e.g. during reconfiguration) as that would mean stale data once the profiler starts again.
|
43
|
+
void gvl_profiling_state_thread_tracking_workaround(void) {
|
44
|
+
if (gvl_profiling_state_thread_tracking_workaround_installed) return;
|
45
|
+
|
46
|
+
rb_internal_thread_add_event_hook(on_thread_start, RUBY_INTERNAL_THREAD_EVENT_STARTED, NULL);
|
47
|
+
|
48
|
+
gvl_profiling_state_thread_tracking_workaround_installed = true;
|
49
|
+
}
|
50
|
+
#endif
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
// This helper is used by the Datadog::Profiling::Collectors::ThreadContext to store data used when profiling the GVL.
|
4
|
+
// It's tested through that class' interfaces.
|
5
|
+
// ---
|
6
|
+
|
7
|
+
#include "extconf.h"
|
8
|
+
|
9
|
+
#if !defined(NO_GVL_INSTRUMENTATION) && !defined(USE_GVL_PROFILING_3_2_WORKAROUNDS) // Ruby 3.3+
|
10
|
+
#include <ruby.h>
|
11
|
+
#include <ruby/thread.h>
|
12
|
+
#include "datadog_ruby_common.h"
|
13
|
+
|
14
|
+
typedef struct { VALUE thread; } gvl_profiling_thread;
|
15
|
+
extern rb_internal_thread_specific_key_t gvl_waiting_tls_key;
|
16
|
+
|
17
|
+
void gvl_profiling_init(void);
|
18
|
+
|
19
|
+
static inline gvl_profiling_thread thread_from_thread_object(VALUE thread) {
|
20
|
+
return (gvl_profiling_thread) {.thread = thread};
|
21
|
+
}
|
22
|
+
|
23
|
+
static inline gvl_profiling_thread thread_from_event(const rb_internal_thread_event_data_t *event_data) {
|
24
|
+
return thread_from_thread_object(event_data->thread);
|
25
|
+
}
|
26
|
+
|
27
|
+
static inline intptr_t gvl_profiling_state_get(gvl_profiling_thread thread) {
|
28
|
+
return (intptr_t) rb_internal_thread_specific_get(thread.thread, gvl_waiting_tls_key);
|
29
|
+
}
|
30
|
+
|
31
|
+
static inline void gvl_profiling_state_set(gvl_profiling_thread thread, intptr_t value) {
|
32
|
+
rb_internal_thread_specific_set(thread.thread, gvl_waiting_tls_key, (void *) value);
|
33
|
+
}
|
34
|
+
#endif
|
35
|
+
|
36
|
+
#ifdef USE_GVL_PROFILING_3_2_WORKAROUNDS // Ruby 3.2
|
37
|
+
typedef struct { void *thread; } gvl_profiling_thread;
|
38
|
+
extern __thread gvl_profiling_thread gvl_waiting_tls;
|
39
|
+
|
40
|
+
static inline void gvl_profiling_init(void) { }
|
41
|
+
|
42
|
+
// This header gets included in private_vm_access.c which can't include datadog_ruby_common.h so we replicate this
|
43
|
+
// helper here
|
44
|
+
#ifdef __GNUC__
|
45
|
+
#define DDTRACE_UNUSED __attribute__((unused))
|
46
|
+
#else
|
47
|
+
#define DDTRACE_UNUSED
|
48
|
+
#endif
|
49
|
+
|
50
|
+
// NOTE: This is a hack that relies on the knowledge that on Ruby 3.2 the
|
51
|
+
// RUBY_INTERNAL_THREAD_EVENT_READY and RUBY_INTERNAL_THREAD_EVENT_RESUMED events always get called on the thread they
|
52
|
+
// are about. Thus, we can use our thread local storage hack to get this data, even though the event doesn't include it.
|
53
|
+
static inline gvl_profiling_thread thread_from_event(DDTRACE_UNUSED const void *event_data) {
|
54
|
+
return gvl_waiting_tls;
|
55
|
+
}
|
56
|
+
|
57
|
+
void gvl_profiling_state_thread_tracking_workaround(void);
|
58
|
+
gvl_profiling_thread gvl_profiling_state_maybe_initialize(void);
|
59
|
+
|
60
|
+
// Implementing these on Ruby 3.2 requires access to private VM things, so the following methods are
|
61
|
+
// implemented in `private_vm_api_access.c`
|
62
|
+
gvl_profiling_thread thread_from_thread_object(VALUE thread);
|
63
|
+
intptr_t gvl_profiling_state_get(gvl_profiling_thread thread);
|
64
|
+
void gvl_profiling_state_set(gvl_profiling_thread thread, intptr_t value);
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#ifndef NO_GVL_INSTRUMENTATION // For all Rubies supporting GVL profiling (3.2+)
|
68
|
+
static inline intptr_t gvl_profiling_state_thread_object_get(VALUE thread) {
|
69
|
+
return gvl_profiling_state_get(thread_from_thread_object(thread));
|
70
|
+
}
|
71
|
+
|
72
|
+
static inline void gvl_profiling_state_thread_object_set(VALUE thread, intptr_t value) {
|
73
|
+
gvl_profiling_state_set(thread_from_thread_object(thread), value);
|
74
|
+
}
|
75
|
+
#endif
|