datadog 2.25.0 → 2.26.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 +18 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +93 -23
- data/ext/datadog_profiling_native_extension/http_transport.c +1 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/core/configuration/components.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +11 -1
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -2
- data/lib/datadog/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cbf89a9582401ec9fcab36ed1c165ccd447e286085668c768c4df83b5dd27d81
|
|
4
|
+
data.tar.gz: 0c915a22c6ba56f7d39cd03a278466100e72769ac013bb26e9bd2204b4f280ee
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d2fefe85cab7cff7273196e57638a62da64b6ab0f84b0a350266b0adbc64ae57249d1ab6beb74bfe0d42a233f5b36855a4210ffeb69573fa4cafa2decc12820
|
|
7
|
+
data.tar.gz: 6b41c594384690eed2a84f1e8046046a72bb29c276e87d6cf048b34df2d24cf54725526f0d6eebed0a523f4334385a1f796cba8a6c1112e46e5d58787410611d
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.26.0] - 2026-01-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* Core: Add process tags to runtime metrics when `DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED` is enabled. ([#5210][])
|
|
10
|
+
* SSI: Add experimental dependency injection validation.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
* Profiling: Improve profiler error reporting. ([#5237][])
|
|
15
|
+
* SSI: Improve injection debug error reporting. ([#5238][])
|
|
16
|
+
|
|
5
17
|
## [2.25.0] - 2026-01-13
|
|
6
18
|
|
|
7
19
|
### Added
|
|
@@ -3437,7 +3449,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3437
3449
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3438
3450
|
|
|
3439
3451
|
|
|
3440
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3452
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.26.0...master
|
|
3453
|
+
[2.26.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.25.0...v2.26.0
|
|
3441
3454
|
[2.25.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.24.0...v2.25.0
|
|
3442
3455
|
[2.24.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.23.0...v2.24.0
|
|
3443
3456
|
[2.23.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.22.0...v2.23.0
|
|
@@ -5100,8 +5113,11 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5100
5113
|
[#5176]: https://github.com/DataDog/dd-trace-rb/issues/5176
|
|
5101
5114
|
[#5194]: https://github.com/DataDog/dd-trace-rb/issues/5194
|
|
5102
5115
|
[#5197]: https://github.com/DataDog/dd-trace-rb/issues/5197
|
|
5116
|
+
[#5210]: https://github.com/DataDog/dd-trace-rb/issues/5210
|
|
5103
5117
|
[#5215]: https://github.com/DataDog/dd-trace-rb/issues/5215
|
|
5104
5118
|
[#5222]: https://github.com/DataDog/dd-trace-rb/issues/5222
|
|
5119
|
+
[#5237]: https://github.com/DataDog/dd-trace-rb/issues/5237
|
|
5120
|
+
[#5238]: https://github.com/DataDog/dd-trace-rb/issues/5238
|
|
5105
5121
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5106
5122
|
[@Azure7111]: https://github.com/Azure7111
|
|
5107
5123
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -5256,4 +5272,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5256
5272
|
[@y-yagi]: https://github.com/y-yagi
|
|
5257
5273
|
[@yujideveloper]: https://github.com/yujideveloper
|
|
5258
5274
|
[@yukimurasawa]: https://github.com/yukimurasawa
|
|
5259
|
-
[@zachmccormick]: https://github.com/zachmccormick
|
|
5275
|
+
[@zachmccormick]: https://github.com/zachmccormick
|
|
@@ -76,8 +76,6 @@
|
|
|
76
76
|
//
|
|
77
77
|
// ---
|
|
78
78
|
|
|
79
|
-
#define ERR_CLOCK_FAIL "failed to get clock time"
|
|
80
|
-
|
|
81
79
|
// Maximum allowed value for an allocation weight. Attempts to use higher values will result in clamping.
|
|
82
80
|
// See https://docs.google.com/document/d/1lWLB714wlLBBq6T4xZyAc4a5wtWhSmr4-hgiPKeErlA/edit#heading=h.ugp0zxcj5iqh
|
|
83
81
|
// (Datadog-only link) for research backing the choice of this value.
|
|
@@ -117,6 +115,7 @@ typedef struct {
|
|
|
117
115
|
// When something goes wrong during sampling, we record the Ruby exception here, so that it can be "re-raised" on
|
|
118
116
|
// the CpuAndWallTimeWorker thread
|
|
119
117
|
VALUE failure_exception;
|
|
118
|
+
const char *failure_exception_during_operation;
|
|
120
119
|
// Used by `_native_stop` to flag the worker thread to start (see comment on `_native_sampling_loop`)
|
|
121
120
|
VALUE stop_thread;
|
|
122
121
|
|
|
@@ -191,17 +190,17 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
191
190
|
static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
|
|
192
191
|
static VALUE _native_sampling_loop(VALUE self, VALUE instance);
|
|
193
192
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread);
|
|
194
|
-
static VALUE stop(VALUE self_instance, VALUE optional_exception);
|
|
195
|
-
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception);
|
|
193
|
+
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation);
|
|
194
|
+
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception, const char *optional_operation_name);
|
|
196
195
|
static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
|
|
197
196
|
static void *run_sampling_trigger_loop(void *state_ptr);
|
|
198
197
|
static void interrupt_sampling_trigger_loop(void *state_ptr);
|
|
199
198
|
static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
200
199
|
static VALUE rescued_sample_from_postponed_job(VALUE self_instance);
|
|
201
|
-
static VALUE handle_sampling_failure(VALUE self_instance, VALUE exception);
|
|
202
200
|
static VALUE _native_current_sigprof_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
203
201
|
static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance);
|
|
204
202
|
static VALUE _native_is_running(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
203
|
+
static VALUE _native_failure_exception_during_operation(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
205
204
|
static void testing_signal_handler(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
|
|
206
205
|
static VALUE _native_install_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
207
206
|
static VALUE _native_remove_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
@@ -209,7 +208,12 @@ static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self);
|
|
|
209
208
|
static VALUE _native_gc_tracepoint(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
210
209
|
static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused);
|
|
211
210
|
static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
212
|
-
static VALUE safely_call(
|
|
211
|
+
static VALUE safely_call(
|
|
212
|
+
VALUE (*function_to_call_safely)(VALUE),
|
|
213
|
+
VALUE function_to_call_safely_arg,
|
|
214
|
+
VALUE instance,
|
|
215
|
+
VALUE (*handle_sampling_failure)(VALUE, VALUE)
|
|
216
|
+
);
|
|
213
217
|
static VALUE _native_simulate_handle_sampling_signal(DDTRACE_UNUSED VALUE self);
|
|
214
218
|
static VALUE _native_simulate_sample_from_postponed_job(DDTRACE_UNUSED VALUE self);
|
|
215
219
|
static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
@@ -226,6 +230,7 @@ static void disable_tracepoints(cpu_and_wall_time_worker_state *state);
|
|
|
226
230
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
|
|
227
231
|
static VALUE rescued_sample_allocation(VALUE tracepoint_data);
|
|
228
232
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
|
|
233
|
+
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state);
|
|
229
234
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
|
|
230
235
|
static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
|
|
231
236
|
static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
|
@@ -235,6 +240,10 @@ static void after_gvl_running_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
|
235
240
|
#endif
|
|
236
241
|
static VALUE rescued_after_gvl_running_from_postponed_job(VALUE self_instance);
|
|
237
242
|
static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
243
|
+
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
244
|
+
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception);
|
|
245
|
+
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception);
|
|
246
|
+
static VALUE handle_sampling_failure_rescued_after_gvl_running_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
238
247
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state);
|
|
239
248
|
static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
240
249
|
|
|
@@ -262,6 +271,7 @@ static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
|
262
271
|
// (e.g. signal handler) where it's impossible or just awkward to pass it as an argument.
|
|
263
272
|
static VALUE active_sampler_instance = Qnil;
|
|
264
273
|
static cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
|
|
274
|
+
static VALUE clock_failure_exception_class = Qnil;
|
|
265
275
|
|
|
266
276
|
// See handle_sampling_signal for details on what this does
|
|
267
277
|
#ifdef NO_POSTPONED_TRIGGER
|
|
@@ -299,6 +309,8 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
299
309
|
VALUE collectors_cpu_and_wall_time_worker_class = rb_define_class_under(collectors_module, "CpuAndWallTimeWorker", rb_cObject);
|
|
300
310
|
// Hosts methods used for testing the native code using RSpec
|
|
301
311
|
VALUE testing_module = rb_define_module_under(collectors_cpu_and_wall_time_worker_class, "Testing");
|
|
312
|
+
clock_failure_exception_class = rb_define_class_under(collectors_cpu_and_wall_time_worker_class, "ClockFailure", rb_eRuntimeError);
|
|
313
|
+
rb_gc_register_mark_object(clock_failure_exception_class);
|
|
302
314
|
|
|
303
315
|
// Instances of the CpuAndWallTimeWorker class are "TypedData" objects.
|
|
304
316
|
// "TypedData" objects are special objects in the Ruby VM that can wrap C structs.
|
|
@@ -318,6 +330,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
318
330
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stats_reset_not_thread_safe", _native_stats_reset_not_thread_safe, 1);
|
|
319
331
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_allocation_count", _native_allocation_count, 0);
|
|
320
332
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_is_running?", _native_is_running, 1);
|
|
333
|
+
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_failure_exception_during_operation", _native_failure_exception_during_operation, 1);
|
|
321
334
|
rb_define_singleton_method(testing_module, "_native_current_sigprof_signal_handler", _native_current_sigprof_signal_handler, 0);
|
|
322
335
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_hold_signals", _native_hold_signals, 0);
|
|
323
336
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_resume_signals", _native_resume_signals, 0);
|
|
@@ -370,6 +383,7 @@ static VALUE _native_new(VALUE klass) {
|
|
|
370
383
|
|
|
371
384
|
atomic_init(&state->should_run, false);
|
|
372
385
|
state->failure_exception = Qnil;
|
|
386
|
+
state->failure_exception_during_operation = NULL;
|
|
373
387
|
state->stop_thread = Qnil;
|
|
374
388
|
|
|
375
389
|
during_sample_exit(state);
|
|
@@ -554,22 +568,24 @@ static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE
|
|
|
554
568
|
|
|
555
569
|
state->stop_thread = worker_thread;
|
|
556
570
|
|
|
557
|
-
return stop(self_instance,
|
|
571
|
+
return stop(self_instance, Qnil, NULL);
|
|
558
572
|
}
|
|
559
573
|
|
|
560
|
-
|
|
574
|
+
// When providing an `optional_exception`, `optional_exception_during_operation` should be provided as well
|
|
575
|
+
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception, const char *optional_exception_during_operation) {
|
|
561
576
|
atomic_store(&state->should_run, false);
|
|
562
577
|
state->failure_exception = optional_exception;
|
|
578
|
+
state->failure_exception_during_operation = optional_exception_during_operation;
|
|
563
579
|
|
|
564
580
|
// Disable the tracepoints as soon as possible, so the VM doesn't keep on calling them
|
|
565
581
|
disable_tracepoints(state);
|
|
566
582
|
}
|
|
567
583
|
|
|
568
|
-
static VALUE stop(VALUE self_instance, VALUE optional_exception) {
|
|
584
|
+
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation) {
|
|
569
585
|
cpu_and_wall_time_worker_state *state;
|
|
570
586
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
571
587
|
|
|
572
|
-
stop_state(state, optional_exception);
|
|
588
|
+
stop_state(state, optional_exception, optional_exception_during_operation);
|
|
573
589
|
|
|
574
590
|
return Qtrue;
|
|
575
591
|
}
|
|
@@ -726,7 +742,12 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
726
742
|
during_sample_enter(state);
|
|
727
743
|
|
|
728
744
|
// Rescue against any exceptions that happen during sampling
|
|
729
|
-
safely_call(
|
|
745
|
+
safely_call(
|
|
746
|
+
rescued_sample_from_postponed_job,
|
|
747
|
+
state->self_instance,
|
|
748
|
+
state->self_instance,
|
|
749
|
+
handle_sampling_failure_rescued_sample_from_postponed_job
|
|
750
|
+
);
|
|
730
751
|
|
|
731
752
|
during_sample_exit(state);
|
|
732
753
|
}
|
|
@@ -763,11 +784,6 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
|
763
784
|
return Qnil;
|
|
764
785
|
}
|
|
765
786
|
|
|
766
|
-
static VALUE handle_sampling_failure(VALUE self_instance, VALUE exception) {
|
|
767
|
-
stop(self_instance, exception);
|
|
768
|
-
return Qnil;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
787
|
// This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
|
|
772
788
|
// It SHOULD NOT be used for other purposes.
|
|
773
789
|
static VALUE _native_current_sigprof_signal_handler(DDTRACE_UNUSED VALUE self) {
|
|
@@ -844,6 +860,15 @@ static VALUE _native_is_running(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
|
844
860
|
return (state != NULL && is_thread_alive(state->owner_thread) && state->self_instance == instance) ? Qtrue : Qfalse;
|
|
845
861
|
}
|
|
846
862
|
|
|
863
|
+
static VALUE _native_failure_exception_during_operation(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
864
|
+
cpu_and_wall_time_worker_state *state;
|
|
865
|
+
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
866
|
+
|
|
867
|
+
if (state->failure_exception_during_operation == NULL) return Qnil;
|
|
868
|
+
|
|
869
|
+
return rb_str_new_cstr(state->failure_exception_during_operation);
|
|
870
|
+
}
|
|
871
|
+
|
|
847
872
|
static void testing_signal_handler(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext) {
|
|
848
873
|
/* Does nothing on purpose */
|
|
849
874
|
}
|
|
@@ -936,14 +961,24 @@ static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
936
961
|
|
|
937
962
|
during_sample_enter(state);
|
|
938
963
|
|
|
939
|
-
safely_call(
|
|
964
|
+
safely_call(
|
|
965
|
+
thread_context_collector_sample_after_gc,
|
|
966
|
+
state->thread_context_collector_instance,
|
|
967
|
+
state->self_instance,
|
|
968
|
+
handle_sampling_failure_thread_context_collector_sample_after_gc
|
|
969
|
+
);
|
|
940
970
|
|
|
941
971
|
during_sample_exit(state);
|
|
942
972
|
}
|
|
943
973
|
|
|
944
974
|
// Equivalent to Ruby begin/rescue call, where we call a C function and jump to the exception handler if an
|
|
945
975
|
// exception gets raised within
|
|
946
|
-
static VALUE safely_call(
|
|
976
|
+
static VALUE safely_call(
|
|
977
|
+
VALUE (*function_to_call_safely)(VALUE),
|
|
978
|
+
VALUE function_to_call_safely_arg,
|
|
979
|
+
VALUE instance,
|
|
980
|
+
VALUE (*handle_sampling_failure)(VALUE, VALUE)
|
|
981
|
+
) {
|
|
947
982
|
VALUE exception_handler_function_arg = instance;
|
|
948
983
|
return rb_rescue2(
|
|
949
984
|
function_to_call_safely,
|
|
@@ -1119,7 +1154,7 @@ static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
|
|
|
1119
1154
|
#define HANDLE_CLOCK_FAILURE(call) ({ \
|
|
1120
1155
|
long _result = (call); \
|
|
1121
1156
|
if (_result == 0) { \
|
|
1122
|
-
|
|
1157
|
+
delayed_error_clock_failure(state); \
|
|
1123
1158
|
return; \
|
|
1124
1159
|
} \
|
|
1125
1160
|
_result; \
|
|
@@ -1203,12 +1238,17 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1203
1238
|
during_sample_enter(state);
|
|
1204
1239
|
|
|
1205
1240
|
// Rescue against any exceptions that happen during sampling
|
|
1206
|
-
safely_call(
|
|
1241
|
+
safely_call(
|
|
1242
|
+
rescued_sample_allocation,
|
|
1243
|
+
Qnil,
|
|
1244
|
+
state->self_instance,
|
|
1245
|
+
handle_sampling_failure_rescued_sample_allocation
|
|
1246
|
+
);
|
|
1207
1247
|
|
|
1208
1248
|
if (state->dynamic_sampling_rate_enabled) {
|
|
1209
1249
|
long now = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
|
1210
1250
|
if (now == 0) {
|
|
1211
|
-
|
|
1251
|
+
delayed_error_clock_failure(state);
|
|
1212
1252
|
// NOTE: Not short-circuiting here to make sure cleanup happens
|
|
1213
1253
|
}
|
|
1214
1254
|
uint64_t sampling_time_ns = discrete_dynamic_sampler_after_sample(&state->allocation_sampler, now);
|
|
@@ -1284,7 +1324,12 @@ static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
|
|
|
1284
1324
|
|
|
1285
1325
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error) {
|
|
1286
1326
|
// If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
|
|
1287
|
-
stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error));
|
|
1327
|
+
stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error), "delayed_error");
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state) {
|
|
1331
|
+
// If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
|
|
1332
|
+
stop_state(state, rb_exc_new_cstr(clock_failure_exception_class, "failed to get clock time"), "delayed_error_clock_failure");
|
|
1288
1333
|
}
|
|
1289
1334
|
|
|
1290
1335
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg) {
|
|
@@ -1365,7 +1410,12 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1365
1410
|
during_sample_enter(state);
|
|
1366
1411
|
|
|
1367
1412
|
// Rescue against any exceptions that happen during sampling
|
|
1368
|
-
safely_call(
|
|
1413
|
+
safely_call(
|
|
1414
|
+
rescued_after_gvl_running_from_postponed_job,
|
|
1415
|
+
state->self_instance,
|
|
1416
|
+
state->self_instance,
|
|
1417
|
+
handle_sampling_failure_rescued_after_gvl_running_from_postponed_job
|
|
1418
|
+
);
|
|
1369
1419
|
|
|
1370
1420
|
during_sample_exit(state);
|
|
1371
1421
|
}
|
|
@@ -1404,6 +1454,26 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1404
1454
|
}
|
|
1405
1455
|
#endif
|
|
1406
1456
|
|
|
1457
|
+
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception) {
|
|
1458
|
+
stop(self_instance, exception, "rescued_sample_from_postponed_job");
|
|
1459
|
+
return Qnil;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception) {
|
|
1463
|
+
stop(self_instance, exception, "thread_context_collector_sample_after_gc");
|
|
1464
|
+
return Qnil;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception) {
|
|
1468
|
+
stop(self_instance, exception, "rescued_sample_allocation");
|
|
1469
|
+
return Qnil;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
static VALUE handle_sampling_failure_rescued_after_gvl_running_from_postponed_job(VALUE self_instance, VALUE exception) {
|
|
1473
|
+
stop(self_instance, exception, "rescued_after_gvl_running_from_postponed_job");
|
|
1474
|
+
return Qnil;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1407
1477
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state) {
|
|
1408
1478
|
// Tell the compiler it's not allowed to reorder the `during_sample` flag with anything that happens after.
|
|
1409
1479
|
//
|
|
@@ -136,6 +136,7 @@ static VALUE perform_export(
|
|
|
136
136
|
files_to_compress_and_export,
|
|
137
137
|
/* files_to_export_unmodified: */ ddog_prof_Exporter_Slice_File_empty(),
|
|
138
138
|
/* optional_additional_tags: */ NULL,
|
|
139
|
+
/* optional_process_tags: */ NULL,
|
|
139
140
|
&internal_metadata,
|
|
140
141
|
&info
|
|
141
142
|
);
|
|
@@ -10,7 +10,7 @@ module Datadog
|
|
|
10
10
|
module LibdatadogExtconfHelpers
|
|
11
11
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
|
12
12
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
|
13
|
-
LIBDATADOG_VERSION = '~>
|
|
13
|
+
LIBDATADOG_VERSION = '~> 25.0.0.1.0'
|
|
14
14
|
|
|
15
15
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
|
16
16
|
# libdatadog are moved after the extension gets compiled.
|
|
@@ -49,6 +49,7 @@ module Datadog
|
|
|
49
49
|
options[:statsd] = settings.runtime_metrics.statsd unless settings.runtime_metrics.statsd.nil?
|
|
50
50
|
options[:services] = [settings.service] unless settings.service.nil?
|
|
51
51
|
options[:experimental_runtime_id_enabled] = settings.runtime_metrics.experimental_runtime_id_enabled
|
|
52
|
+
options[:experimental_propagate_process_tags_enabled] = settings.experimental_propagate_process_tags_enabled
|
|
52
53
|
|
|
53
54
|
Core::Runtime::Metrics.new(logger: logger, telemetry: telemetry, **options)
|
|
54
55
|
end
|
|
@@ -8,6 +8,7 @@ require_relative '../environment/gc'
|
|
|
8
8
|
require_relative '../environment/thread_count'
|
|
9
9
|
require_relative '../environment/vm_cache'
|
|
10
10
|
require_relative '../environment/yjit'
|
|
11
|
+
require_relative '../environment/process'
|
|
11
12
|
|
|
12
13
|
module Datadog
|
|
13
14
|
module Core
|
|
@@ -24,6 +25,9 @@ module Datadog
|
|
|
24
25
|
|
|
25
26
|
# Initialize the collection of runtime-id
|
|
26
27
|
@runtime_id_enabled = options.fetch(:experimental_runtime_id_enabled, false)
|
|
28
|
+
|
|
29
|
+
# Initialized process tags support
|
|
30
|
+
@process_tags_enabled = options.fetch(:experimental_propagate_process_tags_enabled, false)
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
# Associate service with runtime metrics
|
|
@@ -111,6 +115,11 @@ module Datadog
|
|
|
111
115
|
|
|
112
116
|
# Add runtime-id dynamically because it might change during runtime.
|
|
113
117
|
options[:tags].concat(["runtime-id:#{Core::Environment::Identity.id}"]) if @runtime_id_enabled
|
|
118
|
+
|
|
119
|
+
# Add process tags when enabled
|
|
120
|
+
if @process_tags_enabled
|
|
121
|
+
options[:tags].concat(Core::Environment::Process.tags)
|
|
122
|
+
end
|
|
114
123
|
end
|
|
115
124
|
end
|
|
116
125
|
|
|
@@ -119,7 +128,8 @@ module Datadog
|
|
|
119
128
|
attr_reader \
|
|
120
129
|
:service_tags,
|
|
121
130
|
:services,
|
|
122
|
-
:runtime_id_enabled
|
|
131
|
+
:runtime_id_enabled,
|
|
132
|
+
:process_tags_enabled
|
|
123
133
|
|
|
124
134
|
def compile_service_tags!
|
|
125
135
|
@service_tags = services.to_a.collect do |service|
|
|
@@ -77,12 +77,13 @@ module Datadog
|
|
|
77
77
|
Datadog.logger.debug("CpuAndWallTimeWorker thread stopping cleanly")
|
|
78
78
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
79
79
|
@failure_exception = e
|
|
80
|
+
operation_name = self.class._native_failure_exception_during_operation(self).inspect
|
|
80
81
|
Datadog.logger.warn(
|
|
81
82
|
"CpuAndWallTimeWorker thread error. " \
|
|
82
|
-
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
|
83
|
+
"Operation: #{operation_name} Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
|
83
84
|
)
|
|
84
85
|
on_failure_proc&.call
|
|
85
|
-
Datadog::Core::Telemetry::Logger.report(e, description: "CpuAndWallTimeWorker thread error")
|
|
86
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "CpuAndWallTimeWorker thread error: #{operation_name}")
|
|
86
87
|
end
|
|
87
88
|
@worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
|
|
88
89
|
@worker_thread.thread_variable_set(:fork_safe, true)
|
data/lib/datadog/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: datadog
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.26.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Datadog, Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: msgpack
|
|
@@ -33,7 +33,7 @@ dependencies:
|
|
|
33
33
|
version: '3.5'
|
|
34
34
|
- - ">="
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version: 3.5.
|
|
36
|
+
version: 3.5.1
|
|
37
37
|
type: :runtime
|
|
38
38
|
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -43,7 +43,7 @@ dependencies:
|
|
|
43
43
|
version: '3.5'
|
|
44
44
|
- - ">="
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 3.5.
|
|
46
|
+
version: 3.5.1
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: libddwaf
|
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -64,14 +64,14 @@ dependencies:
|
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
67
|
+
version: 25.0.0.1.0
|
|
68
68
|
type: :runtime
|
|
69
69
|
prerelease: false
|
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version:
|
|
74
|
+
version: 25.0.0.1.0
|
|
75
75
|
- !ruby/object:Gem::Dependency
|
|
76
76
|
name: logger
|
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -1090,8 +1090,8 @@ licenses:
|
|
|
1090
1090
|
- Apache-2.0
|
|
1091
1091
|
metadata:
|
|
1092
1092
|
allowed_push_host: https://rubygems.org
|
|
1093
|
-
changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.
|
|
1094
|
-
source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.
|
|
1093
|
+
changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.26.0/CHANGELOG.md
|
|
1094
|
+
source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.26.0
|
|
1095
1095
|
post_install_message:
|
|
1096
1096
|
rdoc_options: []
|
|
1097
1097
|
require_paths:
|