datadog 2.42.0 → 2.43.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 +24 -2
- data/README.md +3 -0
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +10 -0
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +15 -5
- data/ext/datadog_profiling_native_extension/heap_recorder.c +13 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +9 -2
- data/ext/datadog_profiling_native_extension/stack_recorder.c +13 -0
- data/ext/datadog_profiling_native_extension/time_helpers.h +2 -1
- data/ext/libdatadog_api/otel_thread_context.c +15 -0
- data/ext/libdatadog_api/trace_exporter.c +642 -22
- data/lib/datadog/open_feature/transport.rb +5 -0
- data/lib/datadog/profiling/collectors/info.rb +2 -6
- data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
- data/lib/datadog/tracing/contrib/sequel/utils.rb +49 -62
- data/lib/datadog/tracing/otel_thread_context.rb +4 -0
- data/lib/datadog/tracing/transport/native.rb +17 -25
- data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
- data/lib/datadog/tracing/transport/traces.rb +2 -22
- data/lib/datadog/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 154c126111f9b92cc59626264fc83b954b36317f96798bc33a0bcb7784516968
|
|
4
|
+
data.tar.gz: 4098225f4c88a0c3e31b069ca1a17231af4298ca149ce530d0dc4ccc9a8d8db5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a566b1ab03efdf8c881ff7a6af93aff5fc946dc213ea1ccfabc554458ae733769ab98002ea14f039e3b2a19c150b2e208083e35fd0519f34b77ff239247412dd
|
|
7
|
+
data.tar.gz: 3a9f8574b7325c9f6e77da1a7f8ad65b8b6a74426b9dab829db84c8adbe8757c1f09d57d8232085c51d074c60e4a77e017cbdd9bfaa5d9f84efba0ad66869866
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.43.0] - 2026-09-22
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* Core: Add an experimental `libdatadog`-backed native trace transport with full feature parity. Opt in with `DD_EXPERIMENTAL_NATIVE_TRANSPORT_ENABLED=true`. ([#5971][])
|
|
10
|
+
* SSI: Support `force_ruby_platform` during Ruby dependency resolution. ([#6316][])
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
* SSI: Respect transitive application dependencies during Ruby injection. ([#6316][])
|
|
15
|
+
* SSI: Preserve checksums in injected Ruby lockfiles. ([#6320][])
|
|
16
|
+
* SSI: Preserve Bundler selection and `RUBYOPT` options during injection. ([#6316][])
|
|
17
|
+
* SSI: Support versioned and symlinked Bundler launchers. ([#6316][])
|
|
18
|
+
* SSI: Restore Ruby injection for deployment and vendored bundles. ([#6316][])
|
|
19
|
+
* Profiling: Fix a potential sampling race when Ruby is idle. ([#6286][])
|
|
20
|
+
* Profiling: Fix profiler not starting on Ruby 4 due to `undefined symbol: rb_current_box`. ([#6350][])
|
|
21
|
+
|
|
5
22
|
## [2.42.0] - 2026-08-31
|
|
6
23
|
|
|
7
24
|
### Added
|
|
@@ -3776,7 +3793,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3776
3793
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3777
3794
|
|
|
3778
3795
|
|
|
3779
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3796
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.43.0...master
|
|
3797
|
+
[2.43.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.42.0...v2.43.0
|
|
3780
3798
|
[2.42.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.41.0...v2.42.0
|
|
3781
3799
|
[2.41.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.40.0...v2.41.0
|
|
3782
3800
|
[2.40.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.39.0...v2.40.0
|
|
@@ -5610,6 +5628,10 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5610
5628
|
[#6232]: https://github.com/DataDog/dd-trace-rb/issues/6232
|
|
5611
5629
|
[#6234]: https://github.com/DataDog/dd-trace-rb/issues/6234
|
|
5612
5630
|
[#6242]: https://github.com/DataDog/dd-trace-rb/issues/6242
|
|
5631
|
+
[#6286]: https://github.com/DataDog/dd-trace-rb/issues/6286
|
|
5632
|
+
[#6316]: https://github.com/DataDog/dd-trace-rb/issues/6316
|
|
5633
|
+
[#6320]: https://github.com/DataDog/dd-trace-rb/issues/6320
|
|
5634
|
+
[#6350]: https://github.com/DataDog/dd-trace-rb/issues/6350
|
|
5613
5635
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5614
5636
|
[@Azure7111]: https://github.com/Azure7111
|
|
5615
5637
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -5765,4 +5787,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5765
5787
|
[@y-yagi]: https://github.com/y-yagi
|
|
5766
5788
|
[@yujideveloper]: https://github.com/yujideveloper
|
|
5767
5789
|
[@yukimurasawa]: https://github.com/yukimurasawa
|
|
5768
|
-
[@zachmccormick]: https://github.com/zachmccormick
|
|
5790
|
+
[@zachmccormick]: https://github.com/zachmccormick
|
data/README.md
CHANGED
|
@@ -17,8 +17,11 @@ For descriptions of terminology used in APM, take a look at the [APM Terms and C
|
|
|
17
17
|
|
|
18
18
|
For contributing, checkout the [contribution guidelines][contribution docs] and [development guide][development docs].
|
|
19
19
|
|
|
20
|
+
To check that a downloaded gem file was published by this repository, see [how to verify gem provenance][provenance docs].
|
|
21
|
+
|
|
20
22
|
[public docs]: https://docs.datadoghq.com/tracing/setup/ruby/
|
|
21
23
|
[api docs]: https://datadog.github.io/dd-trace-rb/
|
|
22
24
|
[APM glossary]: https://docs.datadoghq.com/tracing/glossary/
|
|
23
25
|
[contribution docs]: https://github.com/DataDog/dd-trace-rb/blob/master/CONTRIBUTING.md
|
|
24
26
|
[development docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/DevelopmentGuide.md
|
|
27
|
+
[provenance docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/Provenance.md
|
|
@@ -740,6 +740,8 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
740
740
|
// a) we get triggered using SIGPROF, and the docs state a second SIGPROF will not interrupt an existing one (see sigaction docs on sa_mask)
|
|
741
741
|
// b) we validate we are in the thread that has the global VM lock; if a different thread gets a signal, it will return early
|
|
742
742
|
// because it will not have the global VM lock
|
|
743
|
+
// c) `simulate_sampling_signal_delivery` calls us directly instead of via a real SIGPROF, and blocks SIGPROF delivery on its
|
|
744
|
+
// thread for the duration of that call, so it can't be nested into by a real SIGPROF either
|
|
743
745
|
|
|
744
746
|
state->stats.signal_handler_enqueued_sample++;
|
|
745
747
|
|
|
@@ -1279,11 +1281,19 @@ void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
|
|
|
1279
1281
|
// This can potentially happen if the CpuAndWallTimeWorker was stopped while the IdleSamplingHelper was trying to execute this action
|
|
1280
1282
|
if (state == NULL) return NULL;
|
|
1281
1283
|
|
|
1284
|
+
// Since this is not a real signal firing, we need to block SIGPROF delivery on this thread to avoid an actual SIGPROF
|
|
1285
|
+
// signal coming in nested and interrupting us on this thread. Thus we respect the invariant of "no nesting" for `handle_sampling_signal`.
|
|
1286
|
+
//
|
|
1287
|
+
// Not needed when `no_signals_workaround_enabled` is set: no SIGPROFs are ever sent in that mode, so there's nothing to mask.
|
|
1288
|
+
if (!state->no_signals_workaround_enabled) block_sigprof_signal_handler_from_running_in_current_thread();
|
|
1289
|
+
|
|
1282
1290
|
state->stats.simulated_signal_delivery++;
|
|
1283
1291
|
|
|
1284
1292
|
// `handle_sampling_signal` does a few things extra on top of `sample_from_postponed_job` so that's why we don't shortcut here
|
|
1285
1293
|
handle_sampling_signal(0, NULL, NULL);
|
|
1286
1294
|
|
|
1295
|
+
if (!state->no_signals_workaround_enabled) unblock_sigprof_signal_handler_from_running_in_current_thread();
|
|
1296
|
+
|
|
1287
1297
|
return NULL; // Unused
|
|
1288
1298
|
}
|
|
1289
1299
|
|
|
@@ -888,7 +888,12 @@ void thread_context_collector_on_gc_start(VALUE self_instance) {
|
|
|
888
888
|
}
|
|
889
889
|
|
|
890
890
|
// Here we record the wall-time first and in on_gc_finish we record it second to try to avoid having wall-time be slightly < cpu-time
|
|
891
|
-
|
|
891
|
+
long wall_time_at_start_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
|
892
|
+
|
|
893
|
+
// If our start timestamp is not OK, we skip tracking this GC as well
|
|
894
|
+
if (wall_time_at_start_ns == 0) return;
|
|
895
|
+
|
|
896
|
+
thread_context->gc_tracking.wall_time_at_start_ns = wall_time_at_start_ns;
|
|
892
897
|
thread_context->gc_tracking.cpu_time_at_start_ns = cpu_time_now_ns(thread_context);
|
|
893
898
|
}
|
|
894
899
|
|
|
@@ -917,7 +922,8 @@ bool thread_context_collector_on_gc_finish(VALUE self_instance) {
|
|
|
917
922
|
long cpu_time_at_start_ns = thread_context->gc_tracking.cpu_time_at_start_ns;
|
|
918
923
|
long wall_time_at_start_ns = thread_context->gc_tracking.wall_time_at_start_ns;
|
|
919
924
|
|
|
920
|
-
|
|
925
|
+
// Both fields are always set and cleared together, so checking one is enough
|
|
926
|
+
if (cpu_time_at_start_ns == INVALID_TIME) {
|
|
921
927
|
// If this happened, it means that on_gc_start was either never called for the thread OR it was called but no thread
|
|
922
928
|
// context existed at the time. The former can be the result of a bug, but since we can't distinguish them, we just
|
|
923
929
|
// do nothing.
|
|
@@ -1443,9 +1449,6 @@ static VALUE _native_per_thread_context(DDTRACE_UNUSED VALUE _self, VALUE collec
|
|
|
1443
1449
|
}
|
|
1444
1450
|
|
|
1445
1451
|
static long update_time_since_previous_sample(long *time_at_previous_sample_ns, long current_time_ns, per_thread_context *thread_context) {
|
|
1446
|
-
// If we didn't have a time for the previous sample, we use the current one
|
|
1447
|
-
if (*time_at_previous_sample_ns == INVALID_TIME) *time_at_previous_sample_ns = current_time_ns;
|
|
1448
|
-
|
|
1449
1452
|
// We don't expect to be sampling a thread (and thus updating these counters) while Ruby is doing GC (between
|
|
1450
1453
|
// `thread_context_collector_on_gc_start` and `thread_context_collector_on_gc_finish`)
|
|
1451
1454
|
if (thread_context->gc_tracking.cpu_time_at_start_ns != INVALID_TIME) {
|
|
@@ -1467,6 +1470,13 @@ static long update_time_since_previous_sample(long *time_at_previous_sample_ns,
|
|
|
1467
1470
|
}
|
|
1468
1471
|
|
|
1469
1472
|
static long update_cpu_time_since_previous_sample(per_thread_context *thread_context, long current_cpu_time_ns) {
|
|
1473
|
+
// A previous `cpu_time_now_ns` may have failed to read the clock and thus invalidated our baseline; in that case we
|
|
1474
|
+
// use the current time, so this sample gets no cpu-time and the next one gets an accurate delta.
|
|
1475
|
+
// Note wall-time never needs this: it is always seeded with a real value in `initialize_context`.
|
|
1476
|
+
if (thread_context->cpu_time_at_previous_sample_ns == INVALID_TIME) {
|
|
1477
|
+
thread_context->cpu_time_at_previous_sample_ns = current_cpu_time_ns;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1470
1480
|
long elapsed_time_ns = update_time_since_previous_sample(
|
|
1471
1481
|
&thread_context->cpu_time_at_previous_sample_ns,
|
|
1472
1482
|
current_cpu_time_ns,
|
|
@@ -1193,6 +1193,19 @@ VALUE heap_recorder_testonly_record_id_for(heap_recorder *heap_recorder, VALUE o
|
|
|
1193
1193
|
return context.result;
|
|
1194
1194
|
}
|
|
1195
1195
|
|
|
1196
|
+
void heap_recorder_testonly_set_object_alloc_gen(heap_recorder *heap_recorder, long record_id, size_t alloc_gen) {
|
|
1197
|
+
if (heap_recorder == NULL) {
|
|
1198
|
+
raise_error(rb_eArgError, "heap_recorder is NULL");
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
object_record *record = NULL;
|
|
1202
|
+
if (!st_lookup(heap_recorder->object_records, (st_data_t) record_id, (st_data_t *) &record)) {
|
|
1203
|
+
raise_error(rb_eArgError, "record_id %ld is not being tracked", record_id);
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
record->object_data.alloc_gen = alloc_gen;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1196
1209
|
void heap_recorder_testonly_exhaust_record_ids(heap_recorder *heap_recorder) {
|
|
1197
1210
|
if (heap_recorder == NULL) {
|
|
1198
1211
|
raise_error(rb_eArgError, "heap_recorder is NULL");
|
|
@@ -190,6 +190,10 @@ VALUE heap_recorder_testonly_is_object_recorded(heap_recorder *heap_recorder, lo
|
|
|
190
190
|
// NOTE: This is a linear scan over the tracked objects; fine for the small numbers tests track.
|
|
191
191
|
VALUE heap_recorder_testonly_record_id_for(heap_recorder *heap_recorder, VALUE obj);
|
|
192
192
|
|
|
193
|
+
// Overrides the GC gen a tracked object is considered to have been allocated in. This lets tests give an object an
|
|
194
|
+
// exact age, instead of relying on an exact number of GCs having run.
|
|
195
|
+
void heap_recorder_testonly_set_object_alloc_gen(heap_recorder *heap_recorder, long record_id, size_t alloc_gen);
|
|
196
|
+
|
|
193
197
|
// Used to ensure that a GC actually triggers an update of the objects
|
|
194
198
|
void heap_recorder_testonly_reset_last_update(heap_recorder *heap_recorder);
|
|
195
199
|
|
|
@@ -982,8 +982,15 @@ VALUE ddtrace_alloc_free_rb_mod_name(VALUE mod) {
|
|
|
982
982
|
// Checking for '#' in the name is equivalent on older Rubies:
|
|
983
983
|
// non-permanent names contain '#' from `#<Module:0x...>` or `#<Class:0x...>` prefixes.
|
|
984
984
|
static bool has_permanent_classpath(DDTRACE_UNUSED VALUE mod, DDTRACE_UNUSED VALUE mod_name) {
|
|
985
|
-
#if defined(
|
|
986
|
-
|
|
985
|
+
#if defined(RCLASS_EXT_PRIME) // 4.0+
|
|
986
|
+
// We can't actually use RCLASS_PERMANENT_CLASSPATH_P(mod) because that uses
|
|
987
|
+
// RCLASS_EXT_READABLE() which uses rb_current_box(), which is a private symbol:
|
|
988
|
+
// https://github.com/DataDog/dd-trace-rb/issues/6338
|
|
989
|
+
// Instead we use `RCLASS_EXT_PRIME(mod)->permanent_classpath`, which is equivalent for our usage:
|
|
990
|
+
// the two can only differ for boxable (= core) modules with no permanent name, i.e. metaclasses like
|
|
991
|
+
// String.singleton_class, and is_metaclass() already replaced those with the attached module, so we display
|
|
992
|
+
// `String.foo` and not `#<Class:String>#foo`. Same for the name in ddtrace_alloc_free_rb_mod_name().
|
|
993
|
+
return RCLASS_EXT_PRIME(mod)->permanent_classpath;
|
|
987
994
|
#elif defined(HAVE_PERMANENT_CLASSPATH) // 3.3 - 3.4
|
|
988
995
|
return RCLASS_EXT(mod)->permanent_classpath;
|
|
989
996
|
#else // 3.2 and older
|
|
@@ -275,6 +275,7 @@ static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE record
|
|
|
275
275
|
static VALUE _native_record_id_for(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE obj);
|
|
276
276
|
static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
277
277
|
static VALUE _native_heap_recorder_exhaust_record_ids(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
278
|
+
static VALUE _native_heap_recorder_set_object_alloc_gen(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE record_id, VALUE alloc_gen);
|
|
278
279
|
static VALUE _native_recorder_heap_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
279
280
|
static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all);
|
|
280
281
|
static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self);
|
|
@@ -313,6 +314,7 @@ void stack_recorder_init(VALUE profiling_module) {
|
|
|
313
314
|
rb_define_singleton_method(testing_module, "_native_record_id_for", _native_record_id_for, 2);
|
|
314
315
|
rb_define_singleton_method(testing_module, "_native_heap_recorder_reset_last_update", _native_heap_recorder_reset_last_update, 1);
|
|
315
316
|
rb_define_singleton_method(testing_module, "_native_heap_recorder_exhaust_record_ids", _native_heap_recorder_exhaust_record_ids, 1);
|
|
317
|
+
rb_define_singleton_method(testing_module, "_native_heap_recorder_set_object_alloc_gen", _native_heap_recorder_set_object_alloc_gen, 3);
|
|
316
318
|
rb_define_singleton_method(testing_module, "_native_recorder_heap_update", _native_recorder_heap_update, 1);
|
|
317
319
|
rb_define_singleton_method(testing_module, "_native_benchmark_intern", _native_benchmark_intern, 4);
|
|
318
320
|
rb_define_singleton_method(testing_module, "_native_test_managed_string_storage_produces_valid_profiles", _native_test_managed_string_storage_produces_valid_profiles, 0);
|
|
@@ -1065,6 +1067,17 @@ static VALUE _native_heap_recorder_exhaust_record_ids(DDTRACE_UNUSED VALUE _self
|
|
|
1065
1067
|
return Qtrue;
|
|
1066
1068
|
}
|
|
1067
1069
|
|
|
1070
|
+
static VALUE _native_heap_recorder_set_object_alloc_gen(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE record_id, VALUE alloc_gen) {
|
|
1071
|
+
ENFORCE_TYPE(record_id, T_FIXNUM);
|
|
1072
|
+
ENFORCE_TYPE(alloc_gen, T_FIXNUM);
|
|
1073
|
+
|
|
1074
|
+
stack_recorder_state *state;
|
|
1075
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
|
1076
|
+
|
|
1077
|
+
heap_recorder_testonly_set_object_alloc_gen(state->heap_recorder, FIX2LONG(record_id), NUM2SIZET(alloc_gen));
|
|
1078
|
+
return Qtrue;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1068
1081
|
static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
|
1069
1082
|
stack_recorder_state *state;
|
|
1070
1083
|
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
|
@@ -16,11 +16,12 @@ typedef enum { RAISE_ON_FAILURE, DO_NOT_RAISE_ON_FAILURE } raise_on_failure_sett
|
|
|
16
16
|
#define INVALID_TIME -1
|
|
17
17
|
|
|
18
18
|
typedef struct {
|
|
19
|
+
// INVALID_TIME until the first conversion, and the only field used to decide if the state needs to be (re)computed
|
|
19
20
|
long system_epoch_ns_reference;
|
|
20
21
|
long delta_to_epoch_ns;
|
|
21
22
|
} monotonic_to_system_epoch_state;
|
|
22
23
|
|
|
23
|
-
#define MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER {.system_epoch_ns_reference = INVALID_TIME
|
|
24
|
+
#define MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER {.system_epoch_ns_reference = INVALID_TIME}
|
|
24
25
|
|
|
25
26
|
static inline long retrieve_clock_as_ns(clockid_t clock_id, raise_on_failure_setting raise_on_failure) {
|
|
26
27
|
struct timespec clock_value;
|
|
@@ -24,6 +24,7 @@ static ID fiber_context_slot;
|
|
|
24
24
|
DDTRACE_UNUSED static bool otel_context_enabled = false;
|
|
25
25
|
|
|
26
26
|
static VALUE native_set(VALUE _self, VALUE trace_id, VALUE span_id, VALUE local_root_span_id);
|
|
27
|
+
static VALUE native_clear(VALUE _self);
|
|
27
28
|
static VALUE native_supported_p(VALUE _self);
|
|
28
29
|
static VALUE native_enable(VALUE _self);
|
|
29
30
|
static VALUE native_read(VALUE _self);
|
|
@@ -35,6 +36,7 @@ void otel_thread_context_init(VALUE tracing_module) {
|
|
|
35
36
|
|
|
36
37
|
rb_define_singleton_method(otel_thread_context_module, "_native_enable", native_enable, 0);
|
|
37
38
|
rb_define_singleton_method(otel_thread_context_module, "_native_set", native_set, 3);
|
|
39
|
+
rb_define_singleton_method(otel_thread_context_module, "_native_clear", native_clear, 0);
|
|
38
40
|
rb_define_singleton_method(otel_thread_context_module, "_native_supported?", native_supported_p, 0);
|
|
39
41
|
|
|
40
42
|
VALUE testing_module = rb_define_module_under(otel_thread_context_module, "Testing");
|
|
@@ -204,6 +206,19 @@ static VALUE native_set(
|
|
|
204
206
|
#endif
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
static VALUE native_clear(DDTRACE_UNUSED VALUE _self) {
|
|
210
|
+
#ifdef __linux__
|
|
211
|
+
if (!otel_context_enabled) return Qfalse;
|
|
212
|
+
|
|
213
|
+
ddog_ThreadContextHandle *detached = ddog_otel_thread_ctx_detach();
|
|
214
|
+
rb_thread_local_aset(rb_thread_current(), fiber_context_slot, Qnil);
|
|
215
|
+
|
|
216
|
+
return detached == NULL ? Qfalse : Qtrue;
|
|
217
|
+
#else
|
|
218
|
+
return Qfalse;
|
|
219
|
+
#endif
|
|
220
|
+
}
|
|
221
|
+
|
|
207
222
|
static VALUE native_read(DDTRACE_UNUSED VALUE _self) {
|
|
208
223
|
#ifdef __linux__
|
|
209
224
|
const uint8_t *raw = otel_thread_ctx_v1;
|