datadog 2.16.0 → 2.18.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 +72 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +12 -46
- data/ext/datadog_profiling_native_extension/collectors_stack.c +227 -49
- data/ext/datadog_profiling_native_extension/collectors_stack.h +19 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +63 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +22 -12
- data/ext/datadog_profiling_native_extension/encoded_profile.h +1 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +239 -363
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/http_transport.c +45 -72
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +1 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -3
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +2 -10
- data/ext/datadog_profiling_native_extension/stack_recorder.c +156 -60
- data/ext/libdatadog_api/crashtracker.c +10 -3
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/library_config.c +54 -12
- data/ext/libdatadog_api/library_config.h +6 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +2 -7
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +65 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +23 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/component.rb +30 -54
- data/lib/datadog/appsec/configuration/settings.rb +60 -2
- data/lib/datadog/appsec/context.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +27 -16
- data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
- data/lib/datadog/appsec/remote.rb +15 -55
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +10 -11
- data/lib/datadog/appsec.rb +4 -7
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -46
- data/lib/datadog/core/configuration/components.rb +31 -24
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/option.rb +27 -27
- data/lib/datadog/core/configuration/option_definition.rb +4 -4
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +32 -20
- data/lib/datadog/core/configuration/stable_config.rb +1 -2
- data/lib/datadog/core/configuration.rb +16 -16
- data/lib/datadog/core/crashtracking/component.rb +2 -1
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/encoding.rb +1 -1
- data/lib/datadog/core/environment/cgroup.rb +10 -12
- data/lib/datadog/core/environment/container.rb +38 -40
- data/lib/datadog/core/environment/ext.rb +6 -6
- data/lib/datadog/core/environment/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +12 -14
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +5 -1
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client.rb +32 -31
- data/lib/datadog/core/remote/component.rb +3 -3
- data/lib/datadog/core/remote/configuration/digest.rb +7 -7
- data/lib/datadog/core/remote/configuration/path.rb +1 -1
- data/lib/datadog/core/remote/configuration/repository.rb +12 -0
- data/lib/datadog/core/remote/transport/http/client.rb +1 -1
- data/lib/datadog/core/remote/transport/http/config.rb +21 -5
- data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -1
- data/lib/datadog/core/runtime/metrics.rb +3 -3
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +39 -24
- data/lib/datadog/core/telemetry/emitter.rb +7 -1
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +269 -0
- data/lib/datadog/core/telemetry/event/base.rb +40 -0
- data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
- data/lib/datadog/core/telemetry/event/log.rb +76 -0
- data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
- data/lib/datadog/core/telemetry/event.rb +17 -475
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +11 -5
- data/lib/datadog/core/telemetry/metric.rb +3 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -2
- data/lib/datadog/core/telemetry/transport/telemetry.rb +0 -1
- data/lib/datadog/core/telemetry/worker.rb +48 -27
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/builder.rb +14 -14
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
- data/lib/datadog/core/utils/duration.rb +32 -32
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/network.rb +6 -6
- data/lib/datadog/core/utils/only_once_successful.rb +16 -5
- data/lib/datadog/core/utils/time.rb +10 -2
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/utils.rb +7 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
- data/lib/datadog/core/worker.rb +1 -1
- data/lib/datadog/core/workers/async.rb +9 -10
- data/lib/datadog/di/instrumenter.rb +52 -2
- data/lib/datadog/di/probe_notification_builder.rb +31 -41
- data/lib/datadog/di/probe_notifier_worker.rb +9 -1
- data/lib/datadog/di/serializer.rb +6 -2
- data/lib/datadog/di/transport/http/input.rb +10 -0
- data/lib/datadog/di/transport/input.rb +10 -2
- data/lib/datadog/error_tracking/component.rb +2 -2
- data/lib/datadog/profiling/collectors/code_provenance.rb +18 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +16 -1
- data/lib/datadog/profiling/component.rb +7 -9
- data/lib/datadog/profiling/ext.rb +0 -13
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +3 -8
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +10 -2
- data/lib/datadog/profiling/stack_recorder.rb +5 -5
- data/lib/datadog/profiling/tag_builder.rb +5 -41
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/tracing/sync_writer.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +12 -4
- data/lib/datadog/tracing/tracer.rb +6 -2
- data/lib/datadog/version.rb +1 -1
- metadata +31 -12
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
- data/lib/datadog/appsec/processor.rb +0 -107
@@ -196,6 +196,10 @@ typedef struct {
|
|
196
196
|
pthread_mutex_t mutex_slot_two;
|
197
197
|
profile_slot profile_slot_two;
|
198
198
|
|
199
|
+
ddog_prof_ManagedStringStorage string_storage;
|
200
|
+
ddog_prof_ManagedStringId label_key_allocation_class;
|
201
|
+
ddog_prof_ManagedStringId label_key_gc_gen_age;
|
202
|
+
|
199
203
|
short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
|
200
204
|
|
201
205
|
uint8_t position_for[ALL_VALUE_TYPES_COUNT];
|
@@ -230,6 +234,7 @@ typedef struct {
|
|
230
234
|
ddog_prof_Profile_SerializeResult result;
|
231
235
|
long heap_profile_build_time_ns;
|
232
236
|
long serialize_no_gvl_time_ns;
|
237
|
+
ddog_prof_MaybeError advance_gen_result;
|
233
238
|
|
234
239
|
// Set by both
|
235
240
|
bool serialize_ran;
|
@@ -256,7 +261,6 @@ static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state
|
|
256
261
|
static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
|
257
262
|
static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp);
|
258
263
|
static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class);
|
259
|
-
static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations);
|
260
264
|
static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
261
265
|
static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
262
266
|
static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
@@ -265,6 +269,8 @@ static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns,
|
|
265
269
|
static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE object_id);
|
266
270
|
static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
267
271
|
static VALUE _native_recorder_after_gc_step(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
272
|
+
static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all);
|
273
|
+
static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self);
|
268
274
|
|
269
275
|
void stack_recorder_init(VALUE profiling_module) {
|
270
276
|
VALUE stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
|
@@ -290,7 +296,6 @@ void stack_recorder_init(VALUE profiling_module) {
|
|
290
296
|
rb_define_singleton_method(testing_module, "_native_slot_two_mutex_locked?", _native_is_slot_two_mutex_locked, 1);
|
291
297
|
rb_define_singleton_method(testing_module, "_native_record_endpoint", _native_record_endpoint, 3);
|
292
298
|
rb_define_singleton_method(testing_module, "_native_track_object", _native_track_object, 4);
|
293
|
-
rb_define_singleton_method(testing_module, "_native_check_heap_hashes", _native_check_heap_hashes, 1);
|
294
299
|
rb_define_singleton_method(testing_module, "_native_start_fake_slow_heap_serialization",
|
295
300
|
_native_start_fake_slow_heap_serialization, 1);
|
296
301
|
rb_define_singleton_method(testing_module, "_native_end_fake_slow_heap_serialization",
|
@@ -300,6 +305,8 @@ void stack_recorder_init(VALUE profiling_module) {
|
|
300
305
|
rb_define_singleton_method(testing_module, "_native_is_object_recorded?", _native_is_object_recorded, 2);
|
301
306
|
rb_define_singleton_method(testing_module, "_native_heap_recorder_reset_last_update", _native_heap_recorder_reset_last_update, 1);
|
302
307
|
rb_define_singleton_method(testing_module, "_native_recorder_after_gc_step", _native_recorder_after_gc_step, 1);
|
308
|
+
rb_define_singleton_method(testing_module, "_native_benchmark_intern", _native_benchmark_intern, 4);
|
309
|
+
rb_define_singleton_method(testing_module, "_native_test_managed_string_storage_produces_valid_profiles", _native_test_managed_string_storage_produces_valid_profiles, 0);
|
303
310
|
|
304
311
|
ok_symbol = ID2SYM(rb_intern_const("ok"));
|
305
312
|
error_symbol = ID2SYM(rb_intern_const("error"));
|
@@ -334,17 +341,27 @@ static VALUE _native_new(VALUE klass) {
|
|
334
341
|
.serialization_time_ns_min = INT64_MAX,
|
335
342
|
};
|
336
343
|
|
337
|
-
// Note: At this point, slot_one_profile/slot_two_profile contain null pointers. Libdatadog validates pointers
|
344
|
+
// Note: At this point, slot_one_profile/slot_two_profile/string_storage contain null pointers. Libdatadog validates pointers
|
338
345
|
// before using them so it's ok for us to go ahead and create the StackRecorder object.
|
339
346
|
|
340
347
|
VALUE stack_recorder = TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
|
341
348
|
|
349
|
+
ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
|
350
|
+
|
351
|
+
if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
|
352
|
+
rb_raise(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
|
353
|
+
}
|
354
|
+
|
355
|
+
state->string_storage = string_storage.ok;
|
356
|
+
state->label_key_allocation_class = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("allocation class"));
|
357
|
+
state->label_key_gc_gen_age = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("gc gen age"));
|
358
|
+
|
359
|
+
initialize_profiles(state, sample_types);
|
360
|
+
|
342
361
|
// NOTE: We initialize this because we want a new recorder to be operational even before #initialize runs and our
|
343
362
|
// default is everything enabled. However, if during recording initialization it turns out we don't want
|
344
363
|
// heap samples, we will free and reset heap_recorder back to NULL.
|
345
|
-
state->heap_recorder = heap_recorder_new();
|
346
|
-
|
347
|
-
initialize_profiles(state, sample_types);
|
364
|
+
state->heap_recorder = heap_recorder_new(state->string_storage);
|
348
365
|
|
349
366
|
return stack_recorder;
|
350
367
|
}
|
@@ -363,7 +380,7 @@ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_Val
|
|
363
380
|
ddog_Timespec start_timestamp = system_epoch_now_timespec();
|
364
381
|
|
365
382
|
ddog_prof_Profile_NewResult slot_one_profile_result =
|
366
|
-
|
383
|
+
ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
|
367
384
|
|
368
385
|
if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
369
386
|
rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
|
@@ -372,7 +389,7 @@ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_Val
|
|
372
389
|
state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
|
373
390
|
|
374
391
|
ddog_prof_Profile_NewResult slot_two_profile_result =
|
375
|
-
|
392
|
+
ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
|
376
393
|
|
377
394
|
if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
378
395
|
// Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
|
@@ -393,6 +410,8 @@ static void stack_recorder_typed_data_free(void *state_ptr) {
|
|
393
410
|
|
394
411
|
heap_recorder_free(state->heap_recorder);
|
395
412
|
|
413
|
+
ddog_prof_ManagedStringStorage_drop(state->string_storage);
|
414
|
+
|
396
415
|
ruby_xfree(state);
|
397
416
|
}
|
398
417
|
|
@@ -519,6 +538,8 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
519
538
|
long heap_iteration_prep_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
520
539
|
// Prepare the iteration on heap recorder we'll be doing outside the GVL. The preparation needs to
|
521
540
|
// happen while holding on to the GVL.
|
541
|
+
// NOTE: While rare, it's possible for the GVL to be released inside this function (see comments on `heap_recorder_update`)
|
542
|
+
// and thus don't assume this is an "atomic" step -- other threads may get some running time in the meanwhile.
|
522
543
|
heap_recorder_prepare_iteration(state->heap_recorder);
|
523
544
|
long heap_iteration_prep_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - heap_iteration_prep_start_time_ns;
|
524
545
|
|
@@ -527,7 +548,7 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
527
548
|
call_serialize_without_gvl_arguments args = {
|
528
549
|
.state = state,
|
529
550
|
.finish_timestamp = finish_timestamp,
|
530
|
-
.serialize_ran = false
|
551
|
+
.serialize_ran = false,
|
531
552
|
};
|
532
553
|
|
533
554
|
while (!args.serialize_ran) {
|
@@ -551,13 +572,9 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
551
572
|
// really cover the full serialization process but it gives a more useful number since it bypasses
|
552
573
|
// the noise of acquiring GVLs and dealing with interruptions which is highly specific to runtime
|
553
574
|
// conditions and over which we really have no control about.
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, serialization_time_ns);
|
558
|
-
state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, serialization_time_ns);
|
559
|
-
state->stats_lifetime.serialization_time_ns_total += serialization_time_ns;
|
560
|
-
}
|
575
|
+
state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, args.serialize_no_gvl_time_ns);
|
576
|
+
state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, args.serialize_no_gvl_time_ns);
|
577
|
+
state->stats_lifetime.serialization_time_ns_total += args.serialize_no_gvl_time_ns;
|
561
578
|
|
562
579
|
ddog_prof_Profile_SerializeResult serialized_profile = args.result;
|
563
580
|
|
@@ -566,14 +583,20 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
566
583
|
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&serialized_profile.err));
|
567
584
|
}
|
568
585
|
|
586
|
+
// Note: If we got here, the profile serialized correctly.
|
587
|
+
// Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it and we
|
588
|
+
// can raise exceptions without worrying about leaking the profile.
|
569
589
|
state->stats_lifetime.serialization_successes++;
|
570
|
-
|
571
|
-
// Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it
|
572
590
|
VALUE encoded_profile = from_ddog_prof_EncodedProfile(serialized_profile.ok);
|
573
591
|
|
592
|
+
ddog_prof_MaybeError result = args.advance_gen_result;
|
593
|
+
if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
|
594
|
+
rb_raise(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&result.some));
|
595
|
+
}
|
596
|
+
|
574
597
|
VALUE start = ruby_time_from(args.slot->start_timestamp);
|
575
598
|
VALUE finish = ruby_time_from(finish_timestamp);
|
576
|
-
VALUE profile_stats = build_profile_stats(args.slot,
|
599
|
+
VALUE profile_stats = build_profile_stats(args.slot, args.serialize_no_gvl_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
|
577
600
|
|
578
601
|
return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_profile, profile_stats));
|
579
602
|
}
|
@@ -696,18 +719,15 @@ static bool add_heap_sample_to_active_profile_without_gvl(heap_recorder_iteratio
|
|
696
719
|
ddog_prof_Label labels[2];
|
697
720
|
size_t label_offset = 0;
|
698
721
|
|
699
|
-
if (object_data->class
|
722
|
+
if (object_data->class.value > 0) {
|
700
723
|
labels[label_offset++] = (ddog_prof_Label) {
|
701
|
-
.
|
702
|
-
.
|
703
|
-
.ptr = object_data->class,
|
704
|
-
.len = strlen(object_data->class),
|
705
|
-
},
|
724
|
+
.key_id = context->state->label_key_allocation_class,
|
725
|
+
.str_id = object_data->class,
|
706
726
|
.num = 0, // This shouldn't be needed but the tracer-2.7 docker image ships a buggy gcc that complains about this
|
707
727
|
};
|
708
728
|
}
|
709
729
|
labels[label_offset++] = (ddog_prof_Label) {
|
710
|
-
.
|
730
|
+
.key_id = context->state->label_key_gc_gen_age,
|
711
731
|
.num = object_data->gen_age,
|
712
732
|
};
|
713
733
|
|
@@ -763,7 +783,6 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
763
783
|
long serialize_no_gvl_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
764
784
|
|
765
785
|
profile_slot *slot_now_inactive = serializer_flip_active_and_inactive_slots(args->state);
|
766
|
-
|
767
786
|
args->slot = slot_now_inactive;
|
768
787
|
|
769
788
|
// Now that we have the inactive profile with all but heap samples, lets fill it with heap data
|
@@ -772,9 +791,10 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
772
791
|
args->heap_profile_build_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
|
773
792
|
|
774
793
|
// Note: The profile gets reset by the serialize call
|
775
|
-
args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->
|
794
|
+
args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->slot->start_timestamp, &args->finish_timestamp);
|
795
|
+
args->advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(args->state->string_storage);
|
776
796
|
args->serialize_ran = true;
|
777
|
-
args->serialize_no_gvl_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
|
797
|
+
args->serialize_no_gvl_time_ns = long_max_of(0, monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns);
|
778
798
|
|
779
799
|
return NULL; // Unused
|
780
800
|
}
|
@@ -918,38 +938,8 @@ static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_ins
|
|
918
938
|
return Qtrue;
|
919
939
|
}
|
920
940
|
|
921
|
-
static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations) {
|
922
|
-
ENFORCE_TYPE(locations, T_ARRAY);
|
923
|
-
size_t locations_len = rb_array_len(locations);
|
924
|
-
ddog_prof_Location locations_arr[locations_len];
|
925
|
-
for (size_t i = 0; i < locations_len; i++) {
|
926
|
-
VALUE location = rb_ary_entry(locations, i);
|
927
|
-
ENFORCE_TYPE(location, T_ARRAY);
|
928
|
-
VALUE name = rb_ary_entry(location, 0);
|
929
|
-
VALUE filename = rb_ary_entry(location, 1);
|
930
|
-
VALUE line = rb_ary_entry(location, 2);
|
931
|
-
ENFORCE_TYPE(name, T_STRING);
|
932
|
-
ENFORCE_TYPE(filename, T_STRING);
|
933
|
-
ENFORCE_TYPE(line, T_FIXNUM);
|
934
|
-
locations_arr[i] = (ddog_prof_Location) {
|
935
|
-
.line = line,
|
936
|
-
.function = (ddog_prof_Function) {
|
937
|
-
.name = char_slice_from_ruby_string(name),
|
938
|
-
.filename = char_slice_from_ruby_string(filename),
|
939
|
-
}
|
940
|
-
};
|
941
|
-
}
|
942
|
-
ddog_prof_Slice_Location ddog_locations = {
|
943
|
-
.len = locations_len,
|
944
|
-
.ptr = locations_arr,
|
945
|
-
};
|
946
|
-
heap_recorder_testonly_assert_hash_matches(ddog_locations);
|
947
|
-
|
948
|
-
return Qnil;
|
949
|
-
}
|
950
|
-
|
951
941
|
static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
|
952
|
-
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile
|
942
|
+
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile);
|
953
943
|
if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
|
954
944
|
rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
|
955
945
|
}
|
@@ -1047,3 +1037,109 @@ static VALUE _native_recorder_after_gc_step(DDTRACE_UNUSED VALUE _self, VALUE re
|
|
1047
1037
|
recorder_after_gc_step(recorder_instance);
|
1048
1038
|
return Qtrue;
|
1049
1039
|
}
|
1040
|
+
|
1041
|
+
static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all) {
|
1042
|
+
ENFORCE_TYPE(string, T_STRING);
|
1043
|
+
ENFORCE_TYPE(times, T_FIXNUM);
|
1044
|
+
ENFORCE_BOOLEAN(use_all);
|
1045
|
+
|
1046
|
+
stack_recorder_state *state;
|
1047
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
1048
|
+
|
1049
|
+
heap_recorder_testonly_benchmark_intern(state->heap_recorder, char_slice_from_ruby_string(string), FIX2INT(times), use_all == Qtrue);
|
1050
|
+
|
1051
|
+
return Qtrue;
|
1052
|
+
}
|
1053
|
+
|
1054
|
+
// See comments in rspec test for details on what we're testing here.
|
1055
|
+
static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self) {
|
1056
|
+
ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
|
1057
|
+
|
1058
|
+
if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
|
1059
|
+
rb_raise(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
ddog_prof_Slice_ValueType sample_types = {.ptr = all_value_types, .len = ALL_VALUE_TYPES_COUNT};
|
1063
|
+
ddog_prof_Profile_NewResult profile = ddog_prof_Profile_with_string_storage(sample_types, NULL, string_storage.ok);
|
1064
|
+
|
1065
|
+
if (profile.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
1066
|
+
rb_raise(rb_eRuntimeError, "Failed to initialize profile: %"PRIsVALUE, get_error_details_and_drop(&profile.err));
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
ddog_prof_ManagedStringId hello = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("hello"));
|
1070
|
+
ddog_prof_ManagedStringId world = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("world"));
|
1071
|
+
ddog_prof_ManagedStringId key = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("key"));
|
1072
|
+
|
1073
|
+
int64_t metric_values[] = {1, 2, 3, 4, 5, 6, 7, 8};
|
1074
|
+
ddog_prof_Label labels[] = {{.key_id = key, .str_id = key}};
|
1075
|
+
|
1076
|
+
ddog_prof_Location locations[] = {
|
1077
|
+
(ddog_prof_Location) {
|
1078
|
+
.mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
|
1079
|
+
.function = {
|
1080
|
+
.name = DDOG_CHARSLICE_C(""),
|
1081
|
+
.name_id = hello,
|
1082
|
+
.filename = DDOG_CHARSLICE_C(""),
|
1083
|
+
.filename_id = world,
|
1084
|
+
},
|
1085
|
+
.line = 1,
|
1086
|
+
}
|
1087
|
+
};
|
1088
|
+
|
1089
|
+
ddog_prof_Profile_Result result = ddog_prof_Profile_add(
|
1090
|
+
&profile.ok,
|
1091
|
+
(ddog_prof_Sample) {
|
1092
|
+
.locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
|
1093
|
+
.values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
|
1094
|
+
.labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
|
1095
|
+
},
|
1096
|
+
0
|
1097
|
+
);
|
1098
|
+
|
1099
|
+
if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
|
1100
|
+
rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
ddog_Timespec finish_timestamp = system_epoch_now_timespec();
|
1104
|
+
ddog_Timespec start_timestamp = {.seconds = finish_timestamp.seconds - 60};
|
1105
|
+
ddog_prof_Profile_SerializeResult serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
|
1106
|
+
|
1107
|
+
if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
|
1108
|
+
rb_raise(rb_eRuntimeError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
ddog_prof_MaybeError advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(string_storage.ok);
|
1112
|
+
|
1113
|
+
if (advance_gen_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
|
1114
|
+
rb_raise(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&advance_gen_result.some));
|
1115
|
+
}
|
1116
|
+
|
1117
|
+
VALUE encoded_pprof_1 = from_ddog_prof_EncodedProfile(serialize_result.ok);
|
1118
|
+
|
1119
|
+
result = ddog_prof_Profile_add(
|
1120
|
+
&profile.ok,
|
1121
|
+
(ddog_prof_Sample) {
|
1122
|
+
.locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
|
1123
|
+
.values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
|
1124
|
+
.labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
|
1125
|
+
},
|
1126
|
+
0
|
1127
|
+
);
|
1128
|
+
|
1129
|
+
if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
|
1130
|
+
rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
|
1134
|
+
|
1135
|
+
if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
|
1136
|
+
rb_raise(rb_eArgError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
VALUE encoded_pprof_2 = from_ddog_prof_EncodedProfile(serialize_result.ok);
|
1140
|
+
|
1141
|
+
ddog_prof_Profile_drop(&profile.ok);
|
1142
|
+
ddog_prof_ManagedStringStorage_drop(string_storage.ok);
|
1143
|
+
|
1144
|
+
return rb_ary_new_from_args(2, encoded_pprof_1, encoded_pprof_2);
|
1145
|
+
}
|
@@ -6,6 +6,8 @@
|
|
6
6
|
static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
7
7
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self);
|
8
8
|
|
9
|
+
static bool first_init = true;
|
10
|
+
|
9
11
|
// Used to report Ruby VM crashes.
|
10
12
|
// Once initialized, segfaults will be reported automatically using libdatadog.
|
11
13
|
|
@@ -62,7 +64,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
62
64
|
// "Process.kill('SEGV', Process.pid)" gets run.
|
63
65
|
//
|
64
66
|
// This actually changed in libdatadog 14, so I could see no issues with `create_alt_stack = true`, but not
|
65
|
-
//
|
67
|
+
// overriding what Ruby set up seems a saner default to keep anyway.
|
66
68
|
.create_alt_stack = false,
|
67
69
|
.use_alt_stack = true,
|
68
70
|
.endpoint = endpoint,
|
@@ -92,9 +94,14 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
92
94
|
|
93
95
|
ddog_VoidResult result =
|
94
96
|
action == start_action ?
|
95
|
-
|
97
|
+
(first_init ?
|
98
|
+
ddog_crasht_init(config, receiver_config, metadata) :
|
99
|
+
ddog_crasht_reconfigure(config, receiver_config, metadata)
|
100
|
+
) :
|
96
101
|
ddog_crasht_update_on_fork(config, receiver_config, metadata);
|
97
102
|
|
103
|
+
first_init = false;
|
104
|
+
|
98
105
|
// Clean up before potentially raising any exceptions
|
99
106
|
ddog_Vec_Tag_drop(tags);
|
100
107
|
ddog_endpoint_drop(endpoint);
|
@@ -108,7 +115,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
108
115
|
}
|
109
116
|
|
110
117
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
|
111
|
-
ddog_VoidResult result =
|
118
|
+
ddog_VoidResult result = ddog_crasht_disable();
|
112
119
|
|
113
120
|
if (result.tag == DDOG_VOID_RESULT_ERR) {
|
114
121
|
rb_raise(rb_eRuntimeError, "Failed to stop the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
|
@@ -72,8 +72,8 @@ if ENV['DDTRACE_DEBUG'] == 'true'
|
|
72
72
|
end
|
73
73
|
|
74
74
|
# If we got here, libdatadog is available and loaded
|
75
|
-
ENV['PKG_CONFIG_PATH'] = "#{ENV[
|
76
|
-
Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV[
|
75
|
+
ENV['PKG_CONFIG_PATH'] = "#{ENV["PKG_CONFIG_PATH"]}:#{Libdatadog.pkgconfig_folder}"
|
76
|
+
Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV["PKG_CONFIG_PATH"].inspect}\n")
|
77
77
|
$stderr.puts("Using libdatadog #{Libdatadog::VERSION} from #{Libdatadog.pkgconfig_folder}")
|
78
78
|
|
79
79
|
unless pkg_config('datadog_profiling_with_rpath')
|
@@ -7,6 +7,10 @@
|
|
7
7
|
static VALUE _native_configurator_new(VALUE klass);
|
8
8
|
static VALUE _native_configurator_get(VALUE self);
|
9
9
|
|
10
|
+
// Used for testing in RSpec
|
11
|
+
static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
12
|
+
static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
13
|
+
|
10
14
|
static VALUE config_vec_class = Qnil;
|
11
15
|
|
12
16
|
// ddog_Configurator memory management
|
@@ -52,20 +56,42 @@ void library_config_init(VALUE core_module) {
|
|
52
56
|
rb_define_alloc_func(configurator_class, _native_configurator_new);
|
53
57
|
rb_define_method(configurator_class, "get", _native_configurator_get, 0);
|
54
58
|
|
59
|
+
// Used for testing in RSpec
|
60
|
+
VALUE testing_module = rb_define_module_under(stable_config_module, "Testing");
|
61
|
+
rb_define_singleton_method(testing_module, "with_local_path", _native_configurator_with_local_path, 2);
|
62
|
+
rb_define_singleton_method(testing_module, "with_fleet_path", _native_configurator_with_fleet_path, 2);
|
63
|
+
|
55
64
|
rb_undef_alloc_func(config_vec_class); // It cannot be created from Ruby code and only serves as an intermediate object for the Ruby GC
|
56
65
|
}
|
57
66
|
|
58
|
-
|
59
|
-
static VALUE _native_configurator_new(DDTRACE_UNUSED VALUE _klass) {
|
60
|
-
/*
|
67
|
+
static VALUE _native_configurator_new(VALUE klass) {
|
61
68
|
ddog_Configurator *configurator = ddog_library_configurator_new(false, DDOG_CHARSLICE_C("ruby"));
|
62
69
|
|
63
70
|
ddog_library_configurator_with_detect_process_info(configurator);
|
64
71
|
|
65
72
|
return TypedData_Wrap_Struct(klass, &configurator_typed_data, configurator);
|
66
|
-
|
73
|
+
}
|
74
|
+
|
75
|
+
static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path) {
|
76
|
+
ddog_Configurator *configurator;
|
77
|
+
TypedData_Get_Struct(rb_configurator, ddog_Configurator, &configurator_typed_data, configurator);
|
78
|
+
|
79
|
+
ENFORCE_TYPE(path, T_STRING);
|
67
80
|
|
68
|
-
|
81
|
+
ddog_library_configurator_with_local_path(configurator, cstr_from_ruby_string(path));
|
82
|
+
|
83
|
+
return Qnil;
|
84
|
+
}
|
85
|
+
|
86
|
+
static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path) {
|
87
|
+
ddog_Configurator *configurator;
|
88
|
+
TypedData_Get_Struct(rb_configurator, ddog_Configurator, &configurator_typed_data, configurator);
|
89
|
+
|
90
|
+
ENFORCE_TYPE(path, T_STRING);
|
91
|
+
|
92
|
+
ddog_library_configurator_with_fleet_path(configurator, cstr_from_ruby_string(path));
|
93
|
+
|
94
|
+
return Qnil;
|
69
95
|
}
|
70
96
|
|
71
97
|
static VALUE _native_configurator_get(VALUE self) {
|
@@ -96,26 +122,42 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
96
122
|
|
97
123
|
VALUE local_config_hash = rb_hash_new();
|
98
124
|
VALUE fleet_config_hash = rb_hash_new();
|
99
|
-
|
100
|
-
|
125
|
+
|
126
|
+
bool local_config_id_set = false;
|
127
|
+
bool fleet_config_id_set = false;
|
128
|
+
VALUE local_hash = rb_hash_new();
|
129
|
+
VALUE fleet_hash = rb_hash_new();
|
101
130
|
for (uintptr_t i = 0; i < config_vec->len; i++) {
|
102
131
|
ddog_LibraryConfig config = config_vec->ptr[i];
|
103
132
|
VALUE selected_hash;
|
104
133
|
if (config.source == DDOG_LIBRARY_CONFIG_SOURCE_LOCAL_STABLE_CONFIG) {
|
105
134
|
selected_hash = local_config_hash;
|
135
|
+
if (!local_config_id_set) {
|
136
|
+
local_config_id_set = true;
|
137
|
+
if (config.config_id.length > 0) {
|
138
|
+
rb_hash_aset(local_hash, ID2SYM(rb_intern("id")), rb_utf8_str_new_cstr(config.config_id.ptr));
|
139
|
+
}
|
140
|
+
}
|
106
141
|
}
|
107
142
|
else {
|
108
143
|
selected_hash = fleet_config_hash;
|
144
|
+
if (!fleet_config_id_set) {
|
145
|
+
fleet_config_id_set = true;
|
146
|
+
if (config.config_id.length > 0) {
|
147
|
+
rb_hash_aset(fleet_hash, ID2SYM(rb_intern("id")), rb_utf8_str_new_cstr(config.config_id.ptr));
|
148
|
+
}
|
149
|
+
}
|
109
150
|
}
|
110
151
|
|
111
|
-
|
112
|
-
rb_hash_aset(selected_hash, rb_str_new(name.ptr, name.length), rb_str_new(config.value.ptr, config.value.length));
|
152
|
+
rb_hash_aset(selected_hash, rb_utf8_str_new_cstr(config.name.ptr), rb_utf8_str_new_cstr(config.value.ptr));
|
113
153
|
}
|
114
|
-
|
154
|
+
|
155
|
+
rb_hash_aset(local_hash, ID2SYM(rb_intern("config")), local_config_hash);
|
156
|
+
rb_hash_aset(fleet_hash, ID2SYM(rb_intern("config")), fleet_config_hash);
|
115
157
|
|
116
158
|
VALUE result = rb_hash_new();
|
117
|
-
rb_hash_aset(result, ID2SYM(rb_intern("local")),
|
118
|
-
rb_hash_aset(result, ID2SYM(rb_intern("fleet")),
|
159
|
+
rb_hash_aset(result, ID2SYM(rb_intern("local")), local_hash);
|
160
|
+
rb_hash_aset(result, ID2SYM(rb_intern("fleet")), fleet_hash);
|
119
161
|
|
120
162
|
RB_GC_GUARD(config_vec_rb);
|
121
163
|
return result;
|
@@ -17,3 +17,9 @@ static inline VALUE log_warning_without_config(VALUE warning) {
|
|
17
17
|
|
18
18
|
return rb_funcall(logger, rb_intern("warn"), 1, warning);
|
19
19
|
}
|
20
|
+
|
21
|
+
static inline ddog_CStr cstr_from_ruby_string(VALUE string) {
|
22
|
+
ENFORCE_TYPE(string, T_STRING);
|
23
|
+
ddog_CStr cstr = {.ptr = RSTRING_PTR(string), .length = RSTRING_LEN(string)};
|
24
|
+
return cstr;
|
25
|
+
}
|
@@ -17,9 +17,9 @@ export DD_RUBY_PLATFORM=`ruby -e 'puts Gem::Platform.local.to_s'`
|
|
17
17
|
mkdir -p my-libdatadog-build/$DD_RUBY_PLATFORM
|
18
18
|
```
|
19
19
|
|
20
|
-
5.
|
21
|
-
6. Tell
|
22
|
-
7.
|
20
|
+
5. From inside of the libdatadog repo, build libdatadog into this folder: `./build-profiling-ffi.sh my-libdatadog-build/$DD_RUBY_PLATFORM`
|
21
|
+
6. Tell Ruby where to find libdatadog: `export LIBDATADOG_VENDOR_OVERRIDE=/full/path/to/my-libdatadog-build/` (Notice no platform here)
|
22
|
+
7. From dd-trace-rb, run `bundle exec rake clean compile`
|
23
23
|
|
24
24
|
If you additionally want to run the profiler test suite, also remember to `export DD_PROFILING_MACOS_TESTING=true` and re-run `rake clean compile`.
|
25
25
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#include <errno.h>
|
2
2
|
#include <stdlib.h>
|
3
3
|
#include <ruby.h>
|
4
|
-
#include <datadog/
|
4
|
+
#include <datadog/library-config.h>
|
5
5
|
|
6
6
|
#include "datadog_ruby_common.h"
|
7
7
|
|
@@ -36,8 +36,7 @@ void process_discovery_init(VALUE core_module) {
|
|
36
36
|
rb_define_singleton_method(process_discovery_class, "_native_close_tracer_memfd", _native_close_tracer_memfd, 2);
|
37
37
|
}
|
38
38
|
|
39
|
-
|
40
|
-
static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
|
39
|
+
static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
41
40
|
VALUE logger;
|
42
41
|
VALUE options;
|
43
42
|
rb_scan_args(argc, argv, "1:", &logger, &options);
|
@@ -61,7 +60,6 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED
|
|
61
60
|
ENFORCE_TYPE(service_env, T_STRING);
|
62
61
|
ENFORCE_TYPE(service_version, T_STRING);
|
63
62
|
|
64
|
-
/*
|
65
63
|
ddog_Result_TracerMemfdHandle result = ddog_store_tracer_metadata(
|
66
64
|
(uint8_t) NUM2UINT(schema_version),
|
67
65
|
char_slice_from_ruby_string(runtime_id),
|
@@ -86,9 +84,6 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED
|
|
86
84
|
VALUE tracer_memfd_class = rb_const_get(self, rb_intern("TracerMemfd"));
|
87
85
|
VALUE tracer_memfd = TypedData_Wrap_Struct(tracer_memfd_class, &tracer_memfd_type, fd);
|
88
86
|
return tracer_memfd;
|
89
|
-
*/
|
90
|
-
|
91
|
-
rb_raise(rb_eNotImpError, "TODO: Not in use yet, waiting for libdatadog 17.1");
|
92
87
|
}
|
93
88
|
|
94
89
|
static VALUE _native_to_rb_int(DDTRACE_UNUSED VALUE _self, VALUE tracer_memfd) {
|
@@ -8,7 +8,7 @@ module Datadog
|
|
8
8
|
module LibdatadogExtconfHelpers
|
9
9
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
10
10
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
11
|
-
LIBDATADOG_VERSION = '~>
|
11
|
+
LIBDATADOG_VERSION = '~> 18.1.0.1.0'
|
12
12
|
|
13
13
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
14
14
|
# libdatadog are moved after the extension gets compiled.
|
@@ -104,7 +104,7 @@ module Datadog
|
|
104
104
|
|
105
105
|
# mkmf sets $PKGCONFIG after the `pkg_config` gets used in extconf.rb. When `pkg_config` is unsuccessful, we use
|
106
106
|
# this helper to decide if we can show more specific error message vs a generic "something went wrong".
|
107
|
-
def self.pkg_config_missing?(command: $PKGCONFIG) #
|
107
|
+
def self.pkg_config_missing?(command: $PKGCONFIG) # standard:disable Style/GlobalVars
|
108
108
|
pkg_config_available = command && xsystem("#{command} --version")
|
109
109
|
|
110
110
|
pkg_config_available != true
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module AppSec
|
7
|
+
module APISecurity
|
8
|
+
# An LRU (Least Recently Used) cache implementation that relies on the
|
9
|
+
# Ruby 1.9+ `Hash` implementation that guarantees insertion order.
|
10
|
+
#
|
11
|
+
# WARNING: This implementation is NOT thread-safe and should be used
|
12
|
+
# in a single-threaded context.
|
13
|
+
class LRUCache
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
def_delegators :@store, :clear, :empty?
|
17
|
+
|
18
|
+
def initialize(max_size)
|
19
|
+
raise ArgumentError, 'max_size must be an Integer' unless max_size.is_a?(Integer)
|
20
|
+
raise ArgumentError, 'max_size must be greater than 0' if max_size <= 0
|
21
|
+
|
22
|
+
@max_size = max_size
|
23
|
+
@store = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# NOTE: Accessing a key moves it to the end of the list.
|
27
|
+
def [](key)
|
28
|
+
if (entry = @store.delete(key))
|
29
|
+
@store[key] = entry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def store(key, value)
|
34
|
+
return @store[key] = value if @store.delete(key)
|
35
|
+
|
36
|
+
# NOTE: evict the oldest entry if store reached the maximum allowed size
|
37
|
+
@store.shift if @store.size >= @max_size
|
38
|
+
@store[key] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
# NOTE: If the key exists, it's moved to the end of the list and
|
42
|
+
# if does not, the given block will be executed and the result
|
43
|
+
# will be stored (which will add it to the end of the list).
|
44
|
+
def fetch_or_store(key)
|
45
|
+
if (entry = @store.delete(key))
|
46
|
+
return @store[key] = entry
|
47
|
+
end
|
48
|
+
|
49
|
+
# NOTE: evict the oldest entry if store reached the maximum allowed size
|
50
|
+
@store.shift if @store.size >= @max_size
|
51
|
+
@store[key] = yield
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|