ddtrace 1.18.0 → 1.23.2
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 +228 -2
- data/LICENSE-3rdparty.csv +1 -1
- data/bin/ddprofrb +15 -0
- data/bin/ddtracerb +3 -1
- data/ext/{ddtrace_profiling_loader/ddtrace_profiling_loader.c → datadog_profiling_loader/datadog_profiling_loader.c} +2 -2
- data/ext/{ddtrace_profiling_loader → datadog_profiling_loader}/extconf.rb +3 -3
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_cpu_and_wall_time_worker.c +312 -117
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +422 -0
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +101 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.c +22 -14
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.h +4 -0
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.c +43 -102
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.h +10 -3
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.c +272 -136
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.h +2 -1
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/extconf.rb +28 -7
- data/ext/datadog_profiling_native_extension/heap_recorder.c +1047 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.h +166 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/helpers.h +6 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/http_transport.c +15 -19
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.c +20 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.h +11 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/native_extension_helpers.rb +50 -4
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.c +19 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.h +4 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/profiling.c +18 -1
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +267 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.h +33 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.c +476 -58
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.h +3 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.h +2 -0
- data/lib/datadog/appsec/contrib/devise/tracking.rb +8 -0
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +45 -14
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/components.rb +7 -6
- data/lib/datadog/core/configuration/option.rb +8 -6
- data/lib/datadog/core/configuration/settings.rb +259 -60
- data/lib/datadog/core/configuration.rb +20 -4
- data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
- data/lib/datadog/core/environment/class_count.rb +6 -6
- data/lib/datadog/core/environment/git.rb +25 -0
- data/lib/datadog/core/environment/identity.rb +18 -48
- data/lib/datadog/core/environment/platform.rb +7 -1
- data/lib/datadog/core/git/ext.rb +2 -23
- data/lib/datadog/core/remote/client/capabilities.rb +1 -1
- data/lib/datadog/core/remote/component.rb +25 -12
- data/lib/datadog/core/remote/ext.rb +1 -0
- data/lib/datadog/core/remote/negotiation.rb +2 -2
- data/lib/datadog/core/remote/tie/tracing.rb +39 -0
- data/lib/datadog/core/remote/tie.rb +27 -0
- data/lib/datadog/core/remote/transport/http/config.rb +1 -1
- data/lib/datadog/core/remote/worker.rb +7 -4
- data/lib/datadog/core/telemetry/client.rb +18 -10
- data/lib/datadog/core/telemetry/emitter.rb +9 -13
- data/lib/datadog/core/telemetry/event.rb +247 -56
- data/lib/datadog/core/telemetry/ext.rb +4 -0
- data/lib/datadog/core/telemetry/heartbeat.rb +1 -3
- data/lib/datadog/core/telemetry/http/ext.rb +4 -1
- data/lib/datadog/core/telemetry/http/response.rb +4 -0
- data/lib/datadog/core/telemetry/http/transport.rb +9 -4
- data/lib/datadog/core/telemetry/request.rb +59 -0
- data/lib/datadog/core/transport/ext.rb +2 -0
- data/lib/datadog/core/utils/url.rb +25 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -2
- data/lib/datadog/opentelemetry.rb +3 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +10 -4
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +36 -12
- data/lib/datadog/profiling/collectors/info.rb +101 -0
- data/lib/datadog/profiling/component.rb +210 -34
- data/lib/datadog/profiling/exporter.rb +23 -6
- data/lib/datadog/profiling/ext.rb +2 -0
- data/lib/datadog/profiling/flush.rb +6 -3
- data/lib/datadog/profiling/http_transport.rb +5 -1
- data/lib/datadog/profiling/load_native_extension.rb +19 -6
- data/lib/datadog/profiling/native_extension.rb +1 -1
- data/lib/datadog/profiling/scheduler.rb +4 -6
- data/lib/datadog/profiling/stack_recorder.rb +19 -4
- data/lib/datadog/profiling/tag_builder.rb +5 -0
- data/lib/datadog/profiling/tasks/exec.rb +3 -3
- data/lib/datadog/profiling/tasks/help.rb +3 -3
- data/lib/datadog/profiling.rb +13 -2
- data/lib/datadog/tracing/configuration/ext.rb +0 -1
- data/lib/datadog/tracing/configuration/settings.rb +2 -1
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_cable/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_view/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_job/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +11 -4
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_support/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/analytics.rb +0 -1
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +11 -1
- data/lib/datadog/tracing/contrib/configurable.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/extensions.rb +6 -2
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -0
- data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/grape/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +2 -2
- data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/kafka/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -1
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +11 -4
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/qless/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/racecar/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +9 -2
- data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +0 -2
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rake/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/patcher.rb +34 -21
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/resque/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sequel/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/shoryuken/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/stripe/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +58 -0
- data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +94 -0
- data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/sampling/matcher.rb +23 -3
- data/lib/datadog/tracing/sampling/rule.rb +7 -2
- data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
- data/lib/datadog/tracing/trace_operation.rb +1 -2
- data/lib/datadog/tracing/transport/http.rb +1 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +31 -0
- data/lib/datadog/tracing.rb +8 -2
- data/lib/ddtrace/version.rb +2 -2
- metadata +71 -61
- data/ext/ddtrace_profiling_native_extension/pid_controller.c +0 -57
- data/ext/ddtrace_profiling_native_extension/pid_controller.h +0 -45
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +0 -110
- data/lib/datadog/core/telemetry/collector.rb +0 -240
- data/lib/datadog/core/telemetry/v1/app_event.rb +0 -52
- data/lib/datadog/core/telemetry/v1/application.rb +0 -92
- data/lib/datadog/core/telemetry/v1/configuration.rb +0 -25
- data/lib/datadog/core/telemetry/v1/dependency.rb +0 -43
- data/lib/datadog/core/telemetry/v1/host.rb +0 -59
- data/lib/datadog/core/telemetry/v1/integration.rb +0 -64
- data/lib/datadog/core/telemetry/v1/product.rb +0 -36
- data/lib/datadog/core/telemetry/v1/telemetry_request.rb +0 -106
- data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +0 -41
- data/lib/datadog/core/telemetry/v2/request.rb +0 -29
- data/lib/datadog/profiling/diagnostics/environment_logger.rb +0 -39
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/NativeExtensionDesign.md +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_from_pthread.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_noop.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.c +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#include <ruby.h>
|
|
2
|
+
#include <datadog/profiling.h>
|
|
3
|
+
|
|
4
|
+
#include "collectors_gc_profiling_helper.h"
|
|
5
|
+
|
|
6
|
+
// This helper is used by the Datadog::Profiling::Collectors::ThreadContext to profile garbage collection.
|
|
7
|
+
// It's tested through that class' interfaces.
|
|
8
|
+
// ---
|
|
9
|
+
|
|
10
|
+
// Used when retrieving GC information from the VM.
|
|
11
|
+
// All these are symbols, but we don't need to mark them since we ask for them to be interned (and thus live forever)
|
|
12
|
+
static VALUE state_sym;
|
|
13
|
+
static VALUE marking_sym;
|
|
14
|
+
static VALUE sweeping_sym;
|
|
15
|
+
static VALUE none_sym;
|
|
16
|
+
static VALUE gc_by_sym;
|
|
17
|
+
static VALUE newobj_sym;
|
|
18
|
+
static VALUE malloc_sym;
|
|
19
|
+
static VALUE method_sym;
|
|
20
|
+
static VALUE capi_sym;
|
|
21
|
+
static VALUE stress_sym;
|
|
22
|
+
static VALUE major_by_sym;
|
|
23
|
+
static VALUE nofree_sym;
|
|
24
|
+
static VALUE oldgen_sym;
|
|
25
|
+
static VALUE shady_sym;
|
|
26
|
+
static VALUE force_sym;
|
|
27
|
+
static VALUE oldmalloc_sym;
|
|
28
|
+
|
|
29
|
+
static ddog_CharSlice major_gc_reason_pretty(VALUE major_gc_reason);
|
|
30
|
+
static ddog_CharSlice gc_cause_pretty(VALUE gc_cause);
|
|
31
|
+
static ddog_CharSlice gc_type_pretty(VALUE major_gc_reason, VALUE gc_state);
|
|
32
|
+
|
|
33
|
+
void gc_profiling_init(void) {
|
|
34
|
+
// This function lazy-interns a few constants, which may trigger allocations. Since we want to call it during GC as
|
|
35
|
+
// well, when allocations are not allowed, we call it once here so that the constants get defined ahead of time.
|
|
36
|
+
rb_gc_latest_gc_info(rb_hash_new());
|
|
37
|
+
|
|
38
|
+
// Used to query and look up the results of GC information
|
|
39
|
+
state_sym = ID2SYM(rb_intern_const("state"));
|
|
40
|
+
marking_sym = ID2SYM(rb_intern_const("marking"));
|
|
41
|
+
sweeping_sym = ID2SYM(rb_intern_const("sweeping"));
|
|
42
|
+
none_sym = ID2SYM(rb_intern_const("none"));
|
|
43
|
+
gc_by_sym = ID2SYM(rb_intern_const("gc_by"));
|
|
44
|
+
newobj_sym = ID2SYM(rb_intern_const("newobj"));
|
|
45
|
+
malloc_sym = ID2SYM(rb_intern_const("malloc"));
|
|
46
|
+
method_sym = ID2SYM(rb_intern_const("method"));
|
|
47
|
+
capi_sym = ID2SYM(rb_intern_const("capi"));
|
|
48
|
+
stress_sym = ID2SYM(rb_intern_const("stress"));
|
|
49
|
+
major_by_sym = ID2SYM(rb_intern_const("major_by"));
|
|
50
|
+
nofree_sym = ID2SYM(rb_intern_const("nofree"));
|
|
51
|
+
oldgen_sym = ID2SYM(rb_intern_const("oldgen"));
|
|
52
|
+
shady_sym = ID2SYM(rb_intern_const("shady"));
|
|
53
|
+
force_sym = ID2SYM(rb_intern_const("force"));
|
|
54
|
+
oldmalloc_sym = ID2SYM(rb_intern_const("oldmalloc"));
|
|
55
|
+
state_sym = ID2SYM(rb_intern_const("state"));
|
|
56
|
+
none_sym = ID2SYM(rb_intern_const("none"));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
bool gc_profiling_has_major_gc_finished(void) {
|
|
60
|
+
return rb_gc_latest_gc_info(state_sym) == none_sym && rb_gc_latest_gc_info(major_by_sym) != Qnil;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
uint8_t gc_profiling_set_metadata(ddog_prof_Label *labels, int labels_length) {
|
|
64
|
+
uint8_t max_label_count =
|
|
65
|
+
1 + // thread id
|
|
66
|
+
1 + // thread name
|
|
67
|
+
1 + // state
|
|
68
|
+
1 + // event
|
|
69
|
+
1 + // gc reason
|
|
70
|
+
1 + // gc cause
|
|
71
|
+
1; // gc type
|
|
72
|
+
|
|
73
|
+
if (max_label_count > labels_length) {
|
|
74
|
+
rb_raise(rb_eArgError, "BUG: gc_profiling_set_metadata invalid labels_length (%d) < max_label_count (%d)", labels_length, max_label_count);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
uint8_t label_pos = 0;
|
|
78
|
+
|
|
79
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
80
|
+
.key = DDOG_CHARSLICE_C("thread id"),
|
|
81
|
+
.str = DDOG_CHARSLICE_C("GC"),
|
|
82
|
+
.num = 0, // This shouldn't be needed but the tracer-2.7 docker image ships a buggy gcc that complains about this
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
86
|
+
.key = DDOG_CHARSLICE_C("thread name"),
|
|
87
|
+
.str = DDOG_CHARSLICE_C("Garbage Collection"),
|
|
88
|
+
.num = 0, // Workaround, same as above
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
92
|
+
.key = DDOG_CHARSLICE_C("state"),
|
|
93
|
+
.str = DDOG_CHARSLICE_C("had cpu"),
|
|
94
|
+
.num = 0, // Workaround, same as above
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
98
|
+
.key = DDOG_CHARSLICE_C("event"),
|
|
99
|
+
.str = DDOG_CHARSLICE_C("gc"),
|
|
100
|
+
.num = 0, // Workaround, same as above
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
VALUE major_by = rb_gc_latest_gc_info(major_by_sym);
|
|
104
|
+
if (major_by != Qnil) {
|
|
105
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
106
|
+
.key = DDOG_CHARSLICE_C("gc reason"),
|
|
107
|
+
.str = major_gc_reason_pretty(major_by),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
112
|
+
.key = DDOG_CHARSLICE_C("gc cause"),
|
|
113
|
+
.str = gc_cause_pretty(rb_gc_latest_gc_info(gc_by_sym)),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
labels[label_pos++] = (ddog_prof_Label) {
|
|
117
|
+
.key = DDOG_CHARSLICE_C("gc type"),
|
|
118
|
+
.str = gc_type_pretty(major_by, rb_gc_latest_gc_info(state_sym)),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (label_pos > max_label_count) {
|
|
122
|
+
rb_raise(rb_eRuntimeError, "BUG: gc_profiling_set_metadata unexpected label_pos (%d) > max_label_count (%d)", label_pos, max_label_count);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return label_pos;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static ddog_CharSlice major_gc_reason_pretty(VALUE major_gc_reason) {
|
|
129
|
+
if (major_gc_reason == nofree_sym ) return DDOG_CHARSLICE_C("not enough free slots (NOFREE)");
|
|
130
|
+
if (major_gc_reason == oldgen_sym ) return DDOG_CHARSLICE_C("old generation full (OLDGEN)");
|
|
131
|
+
if (major_gc_reason == shady_sym ) return DDOG_CHARSLICE_C("too many objects without write barriers (SHADY)");
|
|
132
|
+
if (major_gc_reason == force_sym ) return DDOG_CHARSLICE_C("requested (FORCE)");
|
|
133
|
+
if (major_gc_reason == oldmalloc_sym) return DDOG_CHARSLICE_C("heap bytes allocated threshold (OLDMALLOC)");
|
|
134
|
+
return DDOG_CHARSLICE_C("unknown");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static ddog_CharSlice gc_cause_pretty(VALUE gc_cause) {
|
|
138
|
+
if (gc_cause == newobj_sym) return DDOG_CHARSLICE_C("object allocation");
|
|
139
|
+
if (gc_cause == malloc_sym) return DDOG_CHARSLICE_C("malloc()");
|
|
140
|
+
if (gc_cause == method_sym) return DDOG_CHARSLICE_C("GC.start()");
|
|
141
|
+
if (gc_cause == capi_sym ) return DDOG_CHARSLICE_C("rb_gc()");
|
|
142
|
+
if (gc_cause == stress_sym) return DDOG_CHARSLICE_C("stress");
|
|
143
|
+
return DDOG_CHARSLICE_C("unknown");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static ddog_CharSlice gc_type_pretty(VALUE major_gc_reason, VALUE gc_state) {
|
|
147
|
+
if (major_gc_reason != Qnil) {
|
|
148
|
+
if (gc_state == marking_sym ) return DDOG_CHARSLICE_C("major (ongoing, marking)");
|
|
149
|
+
if (gc_state == sweeping_sym) return DDOG_CHARSLICE_C("major (ongoing, sweeping)");
|
|
150
|
+
return DDOG_CHARSLICE_C("major");
|
|
151
|
+
} else {
|
|
152
|
+
// As we delay flushing events when a minor GC finishes, it's not relevant to include the observed state of the
|
|
153
|
+
// minor GC, as we often won't record a marking -> sweeping -> done cycle, as it happens too quickly.
|
|
154
|
+
return DDOG_CHARSLICE_C("minor");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -11,9 +11,6 @@
|
|
|
11
11
|
// Gathers stack traces from running threads, storing them in a StackRecorder instance
|
|
12
12
|
// This file implements the native bits of the Datadog::Profiling::Collectors::Stack class
|
|
13
13
|
|
|
14
|
-
#define MAX_FRAMES_LIMIT 10000
|
|
15
|
-
#define MAX_FRAMES_LIMIT_AS_STRING "10000"
|
|
16
|
-
|
|
17
14
|
static VALUE missing_string = Qnil;
|
|
18
15
|
|
|
19
16
|
// Used as scratch space during sampling
|
|
@@ -36,23 +33,7 @@ static VALUE _native_sample(
|
|
|
36
33
|
VALUE in_gc
|
|
37
34
|
);
|
|
38
35
|
static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size);
|
|
39
|
-
static void record_placeholder_stack_in_native_code(
|
|
40
|
-
sampling_buffer* buffer,
|
|
41
|
-
VALUE recorder_instance,
|
|
42
|
-
sample_values values,
|
|
43
|
-
sample_labels labels,
|
|
44
|
-
sampling_buffer *record_buffer,
|
|
45
|
-
int extra_frames_in_record_buffer
|
|
46
|
-
);
|
|
47
|
-
static void sample_thread_internal(
|
|
48
|
-
VALUE thread,
|
|
49
|
-
sampling_buffer* buffer,
|
|
50
|
-
VALUE recorder_instance,
|
|
51
|
-
sample_values values,
|
|
52
|
-
sample_labels labels,
|
|
53
|
-
sampling_buffer *record_buffer,
|
|
54
|
-
int extra_frames_in_record_buffer
|
|
55
|
-
);
|
|
36
|
+
static void record_placeholder_stack_in_native_code(sampling_buffer* buffer, VALUE recorder_instance, sample_values values, sample_labels labels);
|
|
56
37
|
|
|
57
38
|
void collectors_stack_init(VALUE profiling_module) {
|
|
58
39
|
VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
|
|
@@ -88,6 +69,7 @@ static VALUE _native_sample(
|
|
|
88
69
|
.cpu_or_wall_samples = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("cpu-samples"), zero)),
|
|
89
70
|
.wall_time_ns = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("wall-time"), zero)),
|
|
90
71
|
.alloc_samples = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("alloc-samples"), zero)),
|
|
72
|
+
.timeline_wall_time_ns = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("timeline"), zero)),
|
|
91
73
|
};
|
|
92
74
|
|
|
93
75
|
long labels_count = RARRAY_LEN(labels_array) + RARRAY_LEN(numeric_labels_array);
|
|
@@ -122,62 +104,29 @@ static VALUE _native_sample(
|
|
|
122
104
|
|
|
123
105
|
ddog_prof_Slice_Label slice_labels = {.ptr = labels, .len = labels_count};
|
|
124
106
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
107
|
+
if (in_gc == Qtrue) {
|
|
108
|
+
record_placeholder_stack(
|
|
109
|
+
buffer,
|
|
110
|
+
recorder_instance,
|
|
111
|
+
values,
|
|
112
|
+
(sample_labels) {.labels = slice_labels, .state_label = state_label},
|
|
113
|
+
DDOG_CHARSLICE_C("Garbage Collection")
|
|
114
|
+
);
|
|
115
|
+
} else {
|
|
116
|
+
sample_thread(
|
|
117
|
+
thread,
|
|
118
|
+
buffer,
|
|
119
|
+
recorder_instance,
|
|
120
|
+
values,
|
|
121
|
+
(sample_labels) {.labels = slice_labels, .state_label = state_label}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
133
124
|
|
|
134
125
|
sampling_buffer_free(buffer);
|
|
135
126
|
|
|
136
127
|
return Qtrue;
|
|
137
128
|
}
|
|
138
129
|
|
|
139
|
-
void sample_thread(
|
|
140
|
-
VALUE thread,
|
|
141
|
-
sampling_buffer* buffer,
|
|
142
|
-
VALUE recorder_instance,
|
|
143
|
-
sample_values values,
|
|
144
|
-
sample_labels labels,
|
|
145
|
-
sample_type type
|
|
146
|
-
) {
|
|
147
|
-
// Samples thread into recorder
|
|
148
|
-
if (type == SAMPLE_REGULAR) {
|
|
149
|
-
sampling_buffer *record_buffer = buffer;
|
|
150
|
-
int extra_frames_in_record_buffer = 0;
|
|
151
|
-
sample_thread_internal(thread, buffer, recorder_instance, values, labels, record_buffer, extra_frames_in_record_buffer);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Samples thread into recorder, including as a top frame in the stack a frame named "Garbage Collection"
|
|
156
|
-
if (type == SAMPLE_IN_GC) {
|
|
157
|
-
ddog_CharSlice function_name = DDOG_CHARSLICE_C("");
|
|
158
|
-
ddog_CharSlice function_filename = DDOG_CHARSLICE_C("Garbage Collection");
|
|
159
|
-
buffer->locations[0] = (ddog_prof_Location) {
|
|
160
|
-
.function = (ddog_prof_Function) {.name = function_name, .filename = function_filename},
|
|
161
|
-
.line = 0
|
|
162
|
-
};
|
|
163
|
-
// To avoid changing sample_thread_internal, we just prepare a new buffer struct that uses the same underlying storage as the
|
|
164
|
-
// original buffer, but has capacity one less, so that we can keep the above Garbage Collection frame untouched.
|
|
165
|
-
sampling_buffer thread_in_gc_buffer = (struct sampling_buffer) {
|
|
166
|
-
.max_frames = buffer->max_frames - 1,
|
|
167
|
-
.stack_buffer = buffer->stack_buffer + 1,
|
|
168
|
-
.lines_buffer = buffer->lines_buffer + 1,
|
|
169
|
-
.is_ruby_frame = buffer->is_ruby_frame + 1,
|
|
170
|
-
.locations = buffer->locations + 1,
|
|
171
|
-
};
|
|
172
|
-
sampling_buffer *record_buffer = buffer; // We pass in the original buffer as the record_buffer, but not as the regular buffer
|
|
173
|
-
int extra_frames_in_record_buffer = 1;
|
|
174
|
-
sample_thread_internal(thread, &thread_in_gc_buffer, recorder_instance, values, labels, record_buffer, extra_frames_in_record_buffer);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
rb_raise(rb_eArgError, "Unexpected value for sample_type: %d", type);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
130
|
#define CHARSLICE_EQUALS(must_be_a_literal, charslice) (strlen("" must_be_a_literal) == charslice.len && strncmp(must_be_a_literal, charslice.ptr, charslice.len) == 0)
|
|
182
131
|
|
|
183
132
|
// Idea: Should we release the global vm lock (GVL) after we get the data from `rb_profile_frames`? That way other Ruby threads
|
|
@@ -189,24 +138,12 @@ void sample_thread(
|
|
|
189
138
|
// * Should we move this into a different thread entirely?
|
|
190
139
|
// * If we don't move it into a different thread, does releasing the GVL on a Ruby thread mean that we're introducing
|
|
191
140
|
// a new thread switch point where there previously was none?
|
|
192
|
-
|
|
193
|
-
// ---
|
|
194
|
-
//
|
|
195
|
-
// Why the weird extra record_buffer and extra_frames_in_record_buffer?
|
|
196
|
-
// The answer is: to support both sample_thread() and sample_thread_in_gc().
|
|
197
|
-
//
|
|
198
|
-
// For sample_thread(), buffer == record_buffer and extra_frames_in_record_buffer == 0, so it's a no-op.
|
|
199
|
-
// For sample_thread_in_gc(), the buffer is a special buffer that is the same as the record_buffer, but with every
|
|
200
|
-
// pointer shifted forward extra_frames_in_record_buffer elements, so that the caller can actually inject those extra
|
|
201
|
-
// frames, and this function doesn't have to care about it.
|
|
202
|
-
static void sample_thread_internal(
|
|
141
|
+
void sample_thread(
|
|
203
142
|
VALUE thread,
|
|
204
143
|
sampling_buffer* buffer,
|
|
205
144
|
VALUE recorder_instance,
|
|
206
145
|
sample_values values,
|
|
207
|
-
sample_labels labels
|
|
208
|
-
sampling_buffer *record_buffer,
|
|
209
|
-
int extra_frames_in_record_buffer
|
|
146
|
+
sample_labels labels
|
|
210
147
|
) {
|
|
211
148
|
int captured_frames = ddtrace_rb_profile_frames(
|
|
212
149
|
thread,
|
|
@@ -218,14 +155,7 @@ static void sample_thread_internal(
|
|
|
218
155
|
);
|
|
219
156
|
|
|
220
157
|
if (captured_frames == PLACEHOLDER_STACK_IN_NATIVE_CODE) {
|
|
221
|
-
record_placeholder_stack_in_native_code(
|
|
222
|
-
buffer,
|
|
223
|
-
recorder_instance,
|
|
224
|
-
values,
|
|
225
|
-
labels,
|
|
226
|
-
record_buffer,
|
|
227
|
-
extra_frames_in_record_buffer
|
|
228
|
-
);
|
|
158
|
+
record_placeholder_stack_in_native_code(buffer, recorder_instance, values, labels);
|
|
229
159
|
return;
|
|
230
160
|
}
|
|
231
161
|
|
|
@@ -332,7 +262,7 @@ static void sample_thread_internal(
|
|
|
332
262
|
|
|
333
263
|
record_sample(
|
|
334
264
|
recorder_instance,
|
|
335
|
-
(ddog_prof_Slice_Location) {.ptr =
|
|
265
|
+
(ddog_prof_Slice_Location) {.ptr = buffer->locations, .len = captured_frames},
|
|
336
266
|
values,
|
|
337
267
|
labels
|
|
338
268
|
);
|
|
@@ -379,24 +309,35 @@ static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer*
|
|
|
379
309
|
//
|
|
380
310
|
// To give customers visibility into these threads, rather than reporting an empty stack, we replace the empty stack
|
|
381
311
|
// with one containing a placeholder frame, so that these threads are properly represented in the UX.
|
|
312
|
+
|
|
382
313
|
static void record_placeholder_stack_in_native_code(
|
|
314
|
+
sampling_buffer* buffer,
|
|
315
|
+
VALUE recorder_instance,
|
|
316
|
+
sample_values values,
|
|
317
|
+
sample_labels labels
|
|
318
|
+
) {
|
|
319
|
+
record_placeholder_stack(
|
|
320
|
+
buffer,
|
|
321
|
+
recorder_instance,
|
|
322
|
+
values,
|
|
323
|
+
labels,
|
|
324
|
+
DDOG_CHARSLICE_C("In native code")
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
void record_placeholder_stack(
|
|
383
329
|
sampling_buffer* buffer,
|
|
384
330
|
VALUE recorder_instance,
|
|
385
331
|
sample_values values,
|
|
386
332
|
sample_labels labels,
|
|
387
|
-
|
|
388
|
-
int extra_frames_in_record_buffer
|
|
333
|
+
ddog_CharSlice placeholder_stack
|
|
389
334
|
) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
buffer->locations[0] = (ddog_prof_Location) {
|
|
393
|
-
.function = (ddog_prof_Function) {.name = function_name, .filename = function_filename},
|
|
394
|
-
.line = 0
|
|
395
|
-
};
|
|
335
|
+
ddog_prof_Function placeholder = {.name = DDOG_CHARSLICE_C(""), .filename = placeholder_stack};
|
|
336
|
+
buffer->locations[0] = (ddog_prof_Location) {.function = placeholder, .line = 0};
|
|
396
337
|
|
|
397
338
|
record_sample(
|
|
398
339
|
recorder_instance,
|
|
399
|
-
(ddog_prof_Slice_Location) {.ptr =
|
|
340
|
+
(ddog_prof_Slice_Location) {.ptr = buffer->locations, .len = 1},
|
|
400
341
|
values,
|
|
401
342
|
labels
|
|
402
343
|
);
|
|
@@ -4,17 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
#include "stack_recorder.h"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
#define MAX_FRAMES_LIMIT 10000
|
|
8
|
+
#define MAX_FRAMES_LIMIT_AS_STRING "10000"
|
|
8
9
|
|
|
9
|
-
typedef
|
|
10
|
+
typedef struct sampling_buffer sampling_buffer;
|
|
10
11
|
|
|
11
12
|
void sample_thread(
|
|
12
13
|
VALUE thread,
|
|
14
|
+
sampling_buffer* buffer,
|
|
15
|
+
VALUE recorder_instance,
|
|
16
|
+
sample_values values,
|
|
17
|
+
sample_labels labels
|
|
18
|
+
);
|
|
19
|
+
void record_placeholder_stack(
|
|
13
20
|
sampling_buffer* buffer,
|
|
14
21
|
VALUE recorder_instance,
|
|
15
22
|
sample_values values,
|
|
16
23
|
sample_labels labels,
|
|
17
|
-
|
|
24
|
+
ddog_CharSlice placeholder_stack
|
|
18
25
|
);
|
|
19
26
|
sampling_buffer *sampling_buffer_new(unsigned int max_frames);
|
|
20
27
|
void sampling_buffer_free(sampling_buffer *buffer);
|