datadog 2.0.0.beta2 → 2.0.0.rc1
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 +57 -1
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +1 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +8 -20
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +18 -10
- data/ext/datadog_profiling_native_extension/crashtracker.c +108 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +9 -23
- data/ext/datadog_profiling_native_extension/heap_recorder.c +38 -3
- data/ext/datadog_profiling_native_extension/heap_recorder.h +5 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +0 -93
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +86 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +4 -0
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +2 -12
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +25 -86
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -5
- data/ext/datadog_profiling_native_extension/stack_recorder.c +156 -55
- data/lib/datadog/appsec/contrib/devise/tracking.rb +8 -0
- data/lib/datadog/core/configuration/settings.rb +10 -79
- data/lib/datadog/core/remote/client.rb +1 -5
- data/lib/datadog/core/remote/configuration/repository.rb +1 -1
- data/lib/datadog/core/remote/dispatcher.rb +3 -3
- data/lib/datadog/core/telemetry/emitter.rb +1 -1
- data/lib/datadog/core/telemetry/http/response.rb +4 -0
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +18 -1
- data/lib/datadog/profiling/component.rb +26 -2
- data/lib/datadog/profiling/crashtracker.rb +91 -0
- data/lib/datadog/profiling/exporter.rb +6 -3
- data/lib/datadog/profiling/http_transport.rb +7 -11
- data/lib/datadog/profiling/profiler.rb +9 -2
- data/lib/datadog/profiling/stack_recorder.rb +6 -2
- data/lib/datadog/profiling.rb +1 -0
- data/lib/datadog/tracing/component.rb +5 -1
- data/lib/datadog/tracing/configuration/dynamic.rb +39 -1
- data/lib/datadog/tracing/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/integration.rb +10 -0
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +43 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +1 -1
- data/lib/datadog/tracing/remote.rb +5 -1
- data/lib/datadog/tracing/sampling/ext.rb +5 -1
- data/lib/datadog/tracing/sampling/matcher.rb +60 -31
- data/lib/datadog/tracing/sampling/rule.rb +12 -5
- data/lib/datadog/tracing/sampling/rule_sampler.rb +17 -1
- data/lib/datadog/tracing/sampling/span/matcher.rb +13 -41
- data/lib/datadog/tracing/span_link.rb +12 -6
- data/lib/datadog/tracing/span_operation.rb +6 -4
- data/lib/datadog/version.rb +1 -1
- metadata +7 -5
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
#include <ruby.h>
|
4
4
|
|
5
|
+
static VALUE log_failure_to_process_tag(VALUE err_details);
|
6
|
+
|
5
7
|
const char *ruby_value_type_to_string(enum ruby_value_type type) {
|
6
8
|
return ruby_value_type_to_char_slice(type).ptr;
|
7
9
|
}
|
@@ -60,3 +62,87 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
|
|
60
62
|
ddog_Error_drop(error);
|
61
63
|
return error_msg_size;
|
62
64
|
}
|
65
|
+
|
66
|
+
__attribute__((warn_unused_result))
|
67
|
+
ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
|
68
|
+
ENFORCE_TYPE(exporter_configuration, T_ARRAY);
|
69
|
+
|
70
|
+
VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
|
71
|
+
ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
|
72
|
+
ID working_mode = SYM2ID(exporter_working_mode);
|
73
|
+
|
74
|
+
ID agentless_id = rb_intern("agentless");
|
75
|
+
ID agent_id = rb_intern("agent");
|
76
|
+
|
77
|
+
if (working_mode != agentless_id && working_mode != agent_id) {
|
78
|
+
rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
|
79
|
+
}
|
80
|
+
|
81
|
+
if (working_mode == agentless_id) {
|
82
|
+
VALUE site = rb_ary_entry(exporter_configuration, 1);
|
83
|
+
VALUE api_key = rb_ary_entry(exporter_configuration, 2);
|
84
|
+
ENFORCE_TYPE(site, T_STRING);
|
85
|
+
ENFORCE_TYPE(api_key, T_STRING);
|
86
|
+
|
87
|
+
return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
|
88
|
+
} else { // agent_id
|
89
|
+
VALUE base_url = rb_ary_entry(exporter_configuration, 1);
|
90
|
+
ENFORCE_TYPE(base_url, T_STRING);
|
91
|
+
|
92
|
+
return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
__attribute__((warn_unused_result))
|
97
|
+
ddog_Vec_Tag convert_tags(VALUE tags_as_array) {
|
98
|
+
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
99
|
+
|
100
|
+
long tags_count = RARRAY_LEN(tags_as_array);
|
101
|
+
ddog_Vec_Tag tags = ddog_Vec_Tag_new();
|
102
|
+
|
103
|
+
for (long i = 0; i < tags_count; i++) {
|
104
|
+
VALUE name_value_pair = rb_ary_entry(tags_as_array, i);
|
105
|
+
|
106
|
+
if (!RB_TYPE_P(name_value_pair, T_ARRAY)) {
|
107
|
+
ddog_Vec_Tag_drop(tags);
|
108
|
+
ENFORCE_TYPE(name_value_pair, T_ARRAY);
|
109
|
+
}
|
110
|
+
|
111
|
+
// Note: We can index the array without checking its size first because rb_ary_entry returns Qnil if out of bounds
|
112
|
+
VALUE tag_name = rb_ary_entry(name_value_pair, 0);
|
113
|
+
VALUE tag_value = rb_ary_entry(name_value_pair, 1);
|
114
|
+
|
115
|
+
if (!(RB_TYPE_P(tag_name, T_STRING) && RB_TYPE_P(tag_value, T_STRING))) {
|
116
|
+
ddog_Vec_Tag_drop(tags);
|
117
|
+
ENFORCE_TYPE(tag_name, T_STRING);
|
118
|
+
ENFORCE_TYPE(tag_value, T_STRING);
|
119
|
+
}
|
120
|
+
|
121
|
+
ddog_Vec_Tag_PushResult push_result =
|
122
|
+
ddog_Vec_Tag_push(&tags, char_slice_from_ruby_string(tag_name), char_slice_from_ruby_string(tag_value));
|
123
|
+
|
124
|
+
if (push_result.tag == DDOG_VEC_TAG_PUSH_RESULT_ERR) {
|
125
|
+
// libdatadog validates tags and may catch invalid tags that ddtrace didn't actually catch.
|
126
|
+
// We warn users about such tags, and then just ignore them.
|
127
|
+
|
128
|
+
int exception_state;
|
129
|
+
rb_protect(log_failure_to_process_tag, get_error_details_and_drop(&push_result.err), &exception_state);
|
130
|
+
|
131
|
+
// Since we are calling into Ruby code, it may raise an exception. Ensure that dynamically-allocated tags
|
132
|
+
// get cleaned before propagating the exception.
|
133
|
+
if (exception_state) {
|
134
|
+
ddog_Vec_Tag_drop(tags);
|
135
|
+
rb_jump_tag(exception_state); // "Re-raise" exception
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
return tags;
|
141
|
+
}
|
142
|
+
|
143
|
+
static VALUE log_failure_to_process_tag(VALUE err_details) {
|
144
|
+
VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
|
145
|
+
VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
|
146
|
+
|
147
|
+
return rb_funcall(logger, rb_intern("warn"), 1, rb_sprintf("Failed to add tag to profiling request: %"PRIsVALUE, err_details));
|
148
|
+
}
|
@@ -40,3 +40,7 @@ ddog_CharSlice ruby_value_type_to_char_slice(enum ruby_value_type type);
|
|
40
40
|
inline static char* string_from_char_slice(ddog_CharSlice slice) {
|
41
41
|
return ruby_strndup(slice.ptr, slice.len);
|
42
42
|
}
|
43
|
+
|
44
|
+
ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration);
|
45
|
+
|
46
|
+
ddog_Vec_Tag convert_tags(VALUE tags_as_array);
|
@@ -15,7 +15,7 @@ module Datadog
|
|
15
15
|
# The MJIT header was introduced on 2.6 and removed on 3.3; for other Rubies we rely on debase-ruby_core_source
|
16
16
|
CAN_USE_MJIT_HEADER = RUBY_VERSION.start_with?('2.6', '2.7', '3.0.', '3.1.', '3.2.')
|
17
17
|
|
18
|
-
LIBDATADOG_VERSION = '~>
|
18
|
+
LIBDATADOG_VERSION = '~> 9.0.0.1.0'
|
19
19
|
|
20
20
|
def self.fail_install_if_missing_extension?
|
21
21
|
ENV[ENV_FAIL_INSTALL_IF_MISSING_EXTENSION].to_s.strip.downcase == 'true'
|
@@ -86,7 +86,6 @@ module Datadog
|
|
86
86
|
on_macos? ||
|
87
87
|
on_unknown_os? ||
|
88
88
|
on_unsupported_cpu_arch? ||
|
89
|
-
on_unsupported_ruby_version? ||
|
90
89
|
expected_to_use_mjit_but_mjit_is_disabled? ||
|
91
90
|
libdatadog_not_available? ||
|
92
91
|
libdatadog_not_usable?
|
@@ -166,7 +165,7 @@ module Datadog
|
|
166
165
|
|
167
166
|
# Validation for this check is done in extconf.rb because it relies on mkmf
|
168
167
|
PKG_CONFIG_IS_MISSING = explain_issue(
|
169
|
-
|
168
|
+
# ----------------------------------------------------------------------------+
|
170
169
|
'the `pkg-config` system tool is missing.',
|
171
170
|
'This issue can usually be fixed by installing one of the following:',
|
172
171
|
'the `pkg-config` package on Homebrew and Debian/Ubuntu-based Linux;',
|
@@ -260,15 +259,6 @@ module Datadog
|
|
260
259
|
architecture_not_supported unless RUBY_PLATFORM.start_with?('x86_64', 'aarch64', 'arm64')
|
261
260
|
end
|
262
261
|
|
263
|
-
private_class_method def self.on_unsupported_ruby_version?
|
264
|
-
ruby_version_not_supported = explain_issue(
|
265
|
-
'the profiler only supports Ruby 2.3 or newer.',
|
266
|
-
suggested: UPGRADE_RUBY,
|
267
|
-
)
|
268
|
-
|
269
|
-
ruby_version_not_supported if RUBY_VERSION.start_with?('2.1.', '2.2.')
|
270
|
-
end
|
271
|
-
|
272
262
|
# On some Rubies, we require the mjit header to be present. If Ruby was installed without MJIT support, we also skip
|
273
263
|
# building the extension.
|
274
264
|
private_class_method def self.expected_to_use_mjit_but_mjit_is_disabled?
|
@@ -129,12 +129,7 @@ bool is_current_thread_holding_the_gvl(void) {
|
|
129
129
|
}
|
130
130
|
#else
|
131
131
|
current_gvl_owner gvl_owner(void) {
|
132
|
-
rb_vm_t *vm =
|
133
|
-
#ifndef NO_GET_VM
|
134
|
-
GET_VM();
|
135
|
-
#else
|
136
|
-
thread_struct_from_object(rb_thread_current())->vm;
|
137
|
-
#endif
|
132
|
+
rb_vm_t *vm = GET_VM();
|
138
133
|
|
139
134
|
// BIG Issue: Ruby < 2.6 did not have the owner field. The really nice thing about the owner field is that it's
|
140
135
|
// "atomic" -- when a thread sets it, it "declares" two things in a single step
|
@@ -163,7 +158,7 @@ bool is_current_thread_holding_the_gvl(void) {
|
|
163
158
|
//
|
164
159
|
// Thus an incorrect `is_current_thread_holding_the_gvl` result may lead to issues inside `rb_postponed_job_register_one`.
|
165
160
|
//
|
166
|
-
// For this reason we currently do not enable the new Ruby profiler on Ruby 2.5
|
161
|
+
// For this reason we currently do not enable the new Ruby profiler on Ruby 2.5 by default, and we print a
|
167
162
|
// warning when customers force-enable it.
|
168
163
|
bool gvl_acquired = vm->gvl.acquired != 0;
|
169
164
|
rb_thread_t *current_owner = vm->running_thread;
|
@@ -213,12 +208,7 @@ uint64_t native_thread_id_for(VALUE thread) {
|
|
213
208
|
// Returns the stack depth by using the same approach as rb_profile_frames and backtrace_each: get the positions
|
214
209
|
// of the end and current frame pointers and subtracting them.
|
215
210
|
ptrdiff_t stack_depth_for(VALUE thread) {
|
216
|
-
|
217
|
-
const rb_execution_context_t *ec = thread_struct_from_object(thread)->ec;
|
218
|
-
#else // Ruby < 2.5
|
219
|
-
const rb_thread_t *ec = thread_struct_from_object(thread);
|
220
|
-
#endif
|
221
|
-
|
211
|
+
const rb_execution_context_t *ec = thread_struct_from_object(thread)->ec;
|
222
212
|
const rb_control_frame_t *cfp = ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
|
223
213
|
|
224
214
|
if (end_cfp == NULL) return 0;
|
@@ -253,12 +243,7 @@ void ddtrace_thread_list(VALUE result_array) {
|
|
253
243
|
rb_ractor_t *current_ractor = ddtrace_get_ractor();
|
254
244
|
ccan_list_for_each(¤t_ractor->threads.set, thread, lt_node) {
|
255
245
|
#else
|
256
|
-
rb_vm_t *vm =
|
257
|
-
#ifndef NO_GET_VM
|
258
|
-
GET_VM();
|
259
|
-
#else
|
260
|
-
thread_struct_from_object(rb_thread_current())->vm;
|
261
|
-
#endif
|
246
|
+
rb_vm_t *vm = GET_VM();
|
262
247
|
list_for_each(&vm->living_threads, thread, vmlt_node) {
|
263
248
|
#endif
|
264
249
|
switch (thread->status) {
|
@@ -394,13 +379,6 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
|
|
394
379
|
// * Add thread argument
|
395
380
|
// * Add is_ruby_frame argument
|
396
381
|
// * Removed `if (lines)` tests -- require/assume that like `buff`, `lines` is always specified
|
397
|
-
// * Support Ruby < 2.5 by using rb_thread_t instead of rb_execution_context_t (which did not exist and was just
|
398
|
-
// part of rb_thread_t)
|
399
|
-
// * Support Ruby < 2.4 by using `RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)` instead of `VM_FRAME_RUBYFRAME_P(cfp)`.
|
400
|
-
// Given that the Ruby 2.3 version of `rb_profile_frames` did not support native methods and thus did not need this
|
401
|
-
// check, how did I figure out what to replace it with? I did it by looking at other places in the VM code where the
|
402
|
-
// code looks exactly the same but Ruby 2.4 uses `VM_FRAME_RUBYFRAME_P` whereas Ruby 2.3 used `RUBY_VM_NORMAL_ISEQ_P`.
|
403
|
-
// Examples of these are `errinfo_place` in `eval.c`, `rb_vm_get_ruby_level_next_cfp` (among others) in `vm.c`, etc.
|
404
382
|
// * Skip dummy frame that shows up in main thread
|
405
383
|
// * Add `end_cfp == NULL` and `end_cfp <= cfp` safety checks. These are used in a bunch of places in
|
406
384
|
// `vm_backtrace.c` (`backtrace_each`, `backtrace_size`, `rb_ec_partial_backtrace_object`) but are conspicuously
|
@@ -449,11 +427,7 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, VALUE *buff, i
|
|
449
427
|
// Modified from upstream: Instead of using `GET_EC` to collect info from the current thread,
|
450
428
|
// support sampling any thread (including the current) passed as an argument
|
451
429
|
rb_thread_t *th = thread_struct_from_object(thread);
|
452
|
-
|
453
|
-
const rb_execution_context_t *ec = th->ec;
|
454
|
-
#else // Ruby < 2.5
|
455
|
-
const rb_thread_t *ec = th;
|
456
|
-
#endif
|
430
|
+
const rb_execution_context_t *ec = th->ec;
|
457
431
|
const rb_control_frame_t *cfp = ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
|
458
432
|
#ifndef NO_JIT_RETURN
|
459
433
|
const rb_control_frame_t *top = cfp;
|
@@ -499,11 +473,7 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, VALUE *buff, i
|
|
499
473
|
// rb_profile_frames does not do this check, but `backtrace_each` (`vm_backtrace.c`) does. This frame is not
|
500
474
|
// exposed by the Ruby backtrace APIs and for now we want to match its behavior 1:1
|
501
475
|
}
|
502
|
-
#ifndef USE_ISEQ_P_INSTEAD_OF_RUBYFRAME_P // Modern Rubies
|
503
476
|
else if (VM_FRAME_RUBYFRAME_P(cfp)) {
|
504
|
-
#else // Ruby < 2.4
|
505
|
-
else if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
506
|
-
#endif
|
507
477
|
if (start > 0) {
|
508
478
|
start--;
|
509
479
|
continue;
|
@@ -719,51 +689,27 @@ check_method_entry(VALUE obj, int can_be_svar)
|
|
719
689
|
}
|
720
690
|
}
|
721
691
|
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
rb_callable_method_entry_t *me;
|
736
|
-
|
737
|
-
while (!VM_ENV_LOCAL_P(ep)) {
|
738
|
-
if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL) return me;
|
739
|
-
ep = VM_ENV_PREV_EP(ep);
|
740
|
-
}
|
741
|
-
|
742
|
-
return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
|
743
|
-
}
|
744
|
-
#else
|
745
|
-
// Taken from upstream vm_insnhelper.c at commit 556e9f726e2b80f6088982c6b43abfe68bfad591 (October 2018, ruby_2_3 branch)
|
746
|
-
// Copyright (C) 2007 Koichi Sasada
|
747
|
-
// to support our custom rb_profile_frames (see above)
|
748
|
-
//
|
749
|
-
// Quite a few macros in this function changed after Ruby 2.3. Rather than trying to fix the Ruby 3.2 version to work
|
750
|
-
// with 2.3 constants, I decided to import the Ruby 2.3 version.
|
751
|
-
//
|
752
|
-
// Modifications: None
|
753
|
-
const rb_callable_method_entry_t *
|
754
|
-
rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
|
755
|
-
{
|
756
|
-
VALUE *ep = cfp->ep;
|
757
|
-
rb_callable_method_entry_t *me;
|
692
|
+
// Taken from upstream vm_insnhelper.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
|
693
|
+
// Copyright (C) 2007 Koichi Sasada
|
694
|
+
// to support our custom rb_profile_frames (see above)
|
695
|
+
//
|
696
|
+
// While older Rubies may have this function, the symbol is not exported which leads to dynamic loader issues, e.g.
|
697
|
+
// `dyld: lazy symbol binding failed: Symbol not found: _rb_vm_frame_method_entry`.
|
698
|
+
//
|
699
|
+
// Modifications: None
|
700
|
+
MJIT_STATIC const rb_callable_method_entry_t *
|
701
|
+
rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
|
702
|
+
{
|
703
|
+
const VALUE *ep = cfp->ep;
|
704
|
+
rb_callable_method_entry_t *me;
|
758
705
|
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
706
|
+
while (!VM_ENV_LOCAL_P(ep)) {
|
707
|
+
if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL) return me;
|
708
|
+
ep = VM_ENV_PREV_EP(ep);
|
709
|
+
}
|
763
710
|
|
764
|
-
|
765
|
-
|
766
|
-
#endif // USE_LEGACY_RB_VM_FRAME_METHOD_ENTRY
|
711
|
+
return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
|
712
|
+
}
|
767
713
|
#endif // RUBY_MJIT_HEADER
|
768
714
|
|
769
715
|
#ifndef NO_RACTORS
|
@@ -880,13 +826,6 @@ static inline int ddtrace_imemo_type(VALUE imemo) {
|
|
880
826
|
// This is used to workaround a VM bug. See "handle_sampling_signal" in "collectors_cpu_and_wall_time_worker" for details.
|
881
827
|
#ifdef NO_POSTPONED_TRIGGER
|
882
828
|
void *objspace_ptr_for_gc_finalize_deferred_workaround(void) {
|
883
|
-
|
884
|
-
#ifndef NO_GET_VM // TODO: Inline GET_VM below once we drop support in dd-trace-rb 2.x for < Ruby 2.5
|
885
|
-
GET_VM();
|
886
|
-
#else
|
887
|
-
thread_struct_from_object(rb_thread_current())->vm;
|
888
|
-
#endif
|
889
|
-
|
890
|
-
return vm->objspace;
|
829
|
+
return GET_VM()->objspace;
|
891
830
|
}
|
892
831
|
#endif
|
@@ -19,6 +19,7 @@ void collectors_dynamic_sampling_rate_init(VALUE profiling_module);
|
|
19
19
|
void collectors_idle_sampling_helper_init(VALUE profiling_module);
|
20
20
|
void collectors_stack_init(VALUE profiling_module);
|
21
21
|
void collectors_thread_context_init(VALUE profiling_module);
|
22
|
+
void crashtracker_init(VALUE profiling_module);
|
22
23
|
void http_transport_init(VALUE profiling_module);
|
23
24
|
void stack_recorder_init(VALUE profiling_module);
|
24
25
|
|
@@ -53,6 +54,7 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
|
|
53
54
|
collectors_idle_sampling_helper_init(profiling_module);
|
54
55
|
collectors_stack_init(profiling_module);
|
55
56
|
collectors_thread_context_init(profiling_module);
|
57
|
+
crashtracker_init(profiling_module);
|
56
58
|
http_transport_init(profiling_module);
|
57
59
|
stack_recorder_init(profiling_module);
|
58
60
|
|
@@ -16,11 +16,6 @@ static inline VALUE process_pending_interruptions(DDTRACE_UNUSED VALUE _) {
|
|
16
16
|
return Qnil;
|
17
17
|
}
|
18
18
|
|
19
|
-
// RB_UNLIKELY is not supported on Ruby 2.3
|
20
|
-
#ifndef RB_UNLIKELY
|
21
|
-
#define RB_UNLIKELY(x) x
|
22
|
-
#endif
|
23
|
-
|
24
19
|
// Calls process_pending_interruptions BUT "rescues" any exceptions to be raised, returning them instead as
|
25
20
|
// a non-zero `pending_exception`.
|
26
21
|
//
|
@@ -82,6 +77,9 @@ NORETURN(
|
|
82
77
|
#define ENFORCE_SUCCESS_HELPER(expression, have_gvl) \
|
83
78
|
{ int result_syserr_errno = expression; if (RB_UNLIKELY(result_syserr_errno)) raise_syserr(result_syserr_errno, have_gvl, ADD_QUOTES(expression), __FILE__, __LINE__, __func__); }
|
84
79
|
|
80
|
+
#define RUBY_NUM_OR_NIL(val, condition, conv) ((val condition) ? conv(val) : Qnil)
|
81
|
+
#define RUBY_AVG_OR_NIL(total, count) ((count == 0) ? Qnil : DBL2NUM(((double) total) / count))
|
82
|
+
|
85
83
|
// Called by ENFORCE_SUCCESS_HELPER; should not be used directly
|
86
84
|
NORETURN(void raise_syserr(
|
87
85
|
int syserr_errno,
|