ddtrace 1.18.0 → 1.23.2
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|