ddtrace 1.5.2 → 1.6.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 +44 -1
- data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +9 -2
- data/ext/ddtrace_profiling_loader/extconf.rb +17 -0
- data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +38 -2
- data/ext/ddtrace_profiling_native_extension/clock_id.h +1 -0
- data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +1 -0
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +517 -42
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +3 -0
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +208 -30
- data/ext/ddtrace_profiling_native_extension/collectors_stack.c +156 -46
- data/ext/ddtrace_profiling_native_extension/collectors_stack.h +11 -2
- data/ext/ddtrace_profiling_native_extension/extconf.rb +11 -1
- data/ext/ddtrace_profiling_native_extension/http_transport.c +83 -64
- data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +4 -4
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +3 -2
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +59 -0
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/ddtrace_profiling_native_extension/profiling.c +10 -0
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +0 -1
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +4 -2
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +45 -29
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +7 -7
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +4 -0
- data/lib/datadog/appsec/event.rb +6 -0
- data/lib/datadog/core/configuration/components.rb +20 -14
- data/lib/datadog/core/configuration/settings.rb +42 -4
- data/lib/datadog/core/diagnostics/environment_logger.rb +5 -1
- data/lib/datadog/core/utils/compression.rb +5 -1
- data/lib/datadog/core.rb +0 -54
- data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +12 -2
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -3
- data/lib/datadog/profiling/exporter.rb +2 -4
- data/lib/datadog/profiling/http_transport.rb +1 -1
- data/lib/datadog/tracing/configuration/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -0
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +2 -0
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +2 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -0
- data/lib/datadog/tracing/contrib/ext.rb +6 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +5 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +7 -1
- data/lib/datadog/tracing/contrib/grpc/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
- data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +22 -0
- data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
- data/lib/datadog/tracing/contrib/hanami/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +44 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +7 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +4 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +12 -0
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -0
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +12 -0
- data/lib/datadog/tracing/contrib/pg/ext.rb +2 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +34 -18
- data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +43 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +32 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +49 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +11 -5
- data/lib/datadog/tracing/contrib/redis/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/redis/patcher.rb +41 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +5 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +2 -0
- data/lib/datadog/tracing/contrib/sinatra/env.rb +12 -23
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +7 -3
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +8 -80
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +14 -9
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +84 -0
- data/lib/datadog/tracing/distributed/headers/datadog.rb +122 -30
- data/lib/datadog/tracing/distributed/headers/ext.rb +2 -0
- data/lib/datadog/tracing/flush.rb +1 -1
- data/lib/datadog/tracing/metadata/ext.rb +8 -0
- data/lib/datadog/tracing/propagation/http.rb +9 -1
- data/lib/datadog/tracing/sampling/ext.rb +31 -0
- data/lib/datadog/tracing/sampling/priority_sampler.rb +46 -4
- data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +8 -9
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +29 -5
- data/lib/datadog/tracing/sampling/rate_sampler.rb +10 -3
- data/lib/datadog/tracing/sampling/rule_sampler.rb +4 -3
- data/lib/datadog/tracing/sampling/span/ext.rb +0 -4
- data/lib/datadog/tracing/sampling/span/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/span/sampler.rb +14 -3
- data/lib/datadog/tracing/trace_digest.rb +3 -0
- data/lib/datadog/tracing/trace_operation.rb +10 -0
- data/lib/datadog/tracing/trace_segment.rb +6 -0
- data/lib/datadog/tracing/tracer.rb +3 -1
- data/lib/datadog/tracing/writer.rb +7 -0
- data/lib/ddtrace/transport/trace_formatter.rb +7 -0
- data/lib/ddtrace/transport/traces.rb +1 -1
- data/lib/ddtrace/version.rb +2 -2
- metadata +18 -14
- data/lib/datadog/profiling/old_ext.rb +0 -42
- data/lib/datadog/profiling/transport/http/api/endpoint.rb +0 -85
- data/lib/datadog/profiling/transport/http/api/instance.rb +0 -38
- data/lib/datadog/profiling/transport/http/api/spec.rb +0 -42
- data/lib/datadog/profiling/transport/http/api.rb +0 -45
- data/lib/datadog/profiling/transport/http/builder.rb +0 -30
- data/lib/datadog/profiling/transport/http/client.rb +0 -37
- data/lib/datadog/profiling/transport/http/response.rb +0 -21
- data/lib/datadog/profiling/transport/http.rb +0 -118
|
@@ -22,13 +22,37 @@ struct sampling_buffer {
|
|
|
22
22
|
VALUE *stack_buffer;
|
|
23
23
|
int *lines_buffer;
|
|
24
24
|
bool *is_ruby_frame;
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
ddog_Location *locations;
|
|
26
|
+
ddog_Line *lines;
|
|
27
27
|
}; // Note: typedef'd in the header to sampling_buffer
|
|
28
28
|
|
|
29
|
-
static VALUE _native_sample(
|
|
29
|
+
static VALUE _native_sample(
|
|
30
|
+
VALUE self,
|
|
31
|
+
VALUE thread,
|
|
32
|
+
VALUE recorder_instance,
|
|
33
|
+
VALUE metric_values_hash,
|
|
34
|
+
VALUE labels_array,
|
|
35
|
+
VALUE max_frames,
|
|
36
|
+
VALUE in_gc
|
|
37
|
+
);
|
|
30
38
|
static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size);
|
|
31
|
-
static void record_placeholder_stack_in_native_code(
|
|
39
|
+
static void record_placeholder_stack_in_native_code(
|
|
40
|
+
sampling_buffer* buffer,
|
|
41
|
+
VALUE recorder_instance,
|
|
42
|
+
ddog_Slice_i64 metric_values,
|
|
43
|
+
ddog_Slice_label 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
|
+
ddog_Slice_i64 metric_values,
|
|
52
|
+
ddog_Slice_label labels,
|
|
53
|
+
sampling_buffer *record_buffer,
|
|
54
|
+
int extra_frames_in_record_buffer
|
|
55
|
+
);
|
|
32
56
|
|
|
33
57
|
void collectors_stack_init(VALUE profiling_module) {
|
|
34
58
|
VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
|
|
@@ -36,7 +60,7 @@ void collectors_stack_init(VALUE profiling_module) {
|
|
|
36
60
|
// Hosts methods used for testing the native code using RSpec
|
|
37
61
|
VALUE testing_module = rb_define_module_under(collectors_stack_class, "Testing");
|
|
38
62
|
|
|
39
|
-
rb_define_singleton_method(testing_module, "_native_sample", _native_sample,
|
|
63
|
+
rb_define_singleton_method(testing_module, "_native_sample", _native_sample, 6);
|
|
40
64
|
|
|
41
65
|
missing_string = rb_str_new2("");
|
|
42
66
|
rb_global_variable(&missing_string);
|
|
@@ -44,7 +68,15 @@ void collectors_stack_init(VALUE profiling_module) {
|
|
|
44
68
|
|
|
45
69
|
// This method exists only to enable testing Datadog::Profiling::Collectors::Stack behavior using RSpec.
|
|
46
70
|
// It SHOULD NOT be used for other purposes.
|
|
47
|
-
static VALUE _native_sample(
|
|
71
|
+
static VALUE _native_sample(
|
|
72
|
+
DDTRACE_UNUSED VALUE _self,
|
|
73
|
+
VALUE thread,
|
|
74
|
+
VALUE recorder_instance,
|
|
75
|
+
VALUE metric_values_hash,
|
|
76
|
+
VALUE labels_array,
|
|
77
|
+
VALUE max_frames,
|
|
78
|
+
VALUE in_gc
|
|
79
|
+
) {
|
|
48
80
|
ENFORCE_TYPE(metric_values_hash, T_HASH);
|
|
49
81
|
ENFORCE_TYPE(labels_array, T_ARRAY);
|
|
50
82
|
|
|
@@ -64,12 +96,12 @@ static VALUE _native_sample(DDTRACE_UNUSED VALUE _self, VALUE thread, VALUE reco
|
|
|
64
96
|
}
|
|
65
97
|
|
|
66
98
|
long labels_count = RARRAY_LEN(labels_array);
|
|
67
|
-
|
|
99
|
+
ddog_Label labels[labels_count];
|
|
68
100
|
|
|
69
101
|
for (int i = 0; i < labels_count; i++) {
|
|
70
102
|
VALUE key_str_pair = rb_ary_entry(labels_array, i);
|
|
71
103
|
|
|
72
|
-
labels[i] = (
|
|
104
|
+
labels[i] = (ddog_Label) {
|
|
73
105
|
.key = char_slice_from_ruby_string(rb_ary_entry(key_str_pair, 0)),
|
|
74
106
|
.str = char_slice_from_ruby_string(rb_ary_entry(key_str_pair, 1))
|
|
75
107
|
};
|
|
@@ -84,8 +116,9 @@ static VALUE _native_sample(DDTRACE_UNUSED VALUE _self, VALUE thread, VALUE reco
|
|
|
84
116
|
thread,
|
|
85
117
|
buffer,
|
|
86
118
|
recorder_instance,
|
|
87
|
-
(
|
|
88
|
-
(
|
|
119
|
+
(ddog_Slice_i64) {.ptr = metric_values, .len = ENABLED_VALUE_TYPES_COUNT},
|
|
120
|
+
(ddog_Slice_label) {.ptr = labels, .len = labels_count},
|
|
121
|
+
RTEST(in_gc) ? SAMPLE_IN_GC : SAMPLE_REGULAR
|
|
89
122
|
);
|
|
90
123
|
|
|
91
124
|
sampling_buffer_free(buffer);
|
|
@@ -93,7 +126,78 @@ static VALUE _native_sample(DDTRACE_UNUSED VALUE _self, VALUE thread, VALUE reco
|
|
|
93
126
|
return Qtrue;
|
|
94
127
|
}
|
|
95
128
|
|
|
96
|
-
void sample_thread(
|
|
129
|
+
void sample_thread(
|
|
130
|
+
VALUE thread,
|
|
131
|
+
sampling_buffer* buffer,
|
|
132
|
+
VALUE recorder_instance,
|
|
133
|
+
ddog_Slice_i64 metric_values,
|
|
134
|
+
ddog_Slice_label labels,
|
|
135
|
+
sample_type type
|
|
136
|
+
) {
|
|
137
|
+
// Samples thread into recorder
|
|
138
|
+
if (type == SAMPLE_REGULAR) {
|
|
139
|
+
sampling_buffer *record_buffer = buffer;
|
|
140
|
+
int extra_frames_in_record_buffer = 0;
|
|
141
|
+
sample_thread_internal(thread, buffer, recorder_instance, metric_values, labels, record_buffer, extra_frames_in_record_buffer);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Samples thread into recorder, including as a top frame in the stack a frame named "Garbage Collection"
|
|
146
|
+
if (type == SAMPLE_IN_GC) {
|
|
147
|
+
buffer->lines[0] = (ddog_Line) {
|
|
148
|
+
.function = (ddog_Function) {
|
|
149
|
+
.name = DDOG_CHARSLICE_C(""),
|
|
150
|
+
.filename = DDOG_CHARSLICE_C("Garbage Collection")
|
|
151
|
+
},
|
|
152
|
+
.line = 0
|
|
153
|
+
};
|
|
154
|
+
// To avoid changing sample_thread_internal, we just prepare a new buffer struct that uses the same underlying storage as the
|
|
155
|
+
// original buffer, but has capacity one less, so that we can keep the above Garbage Collection frame untouched.
|
|
156
|
+
sampling_buffer thread_in_gc_buffer = (struct sampling_buffer) {
|
|
157
|
+
.max_frames = buffer->max_frames - 1,
|
|
158
|
+
.stack_buffer = buffer->stack_buffer + 1,
|
|
159
|
+
.lines_buffer = buffer->lines_buffer + 1,
|
|
160
|
+
.is_ruby_frame = buffer->is_ruby_frame + 1,
|
|
161
|
+
.locations = buffer->locations + 1,
|
|
162
|
+
.lines = buffer->lines + 1
|
|
163
|
+
};
|
|
164
|
+
sampling_buffer *record_buffer = buffer; // We pass in the original buffer as the record_buffer, but not as the regular buffer
|
|
165
|
+
int extra_frames_in_record_buffer = 1;
|
|
166
|
+
sample_thread_internal(thread, &thread_in_gc_buffer, recorder_instance, metric_values, labels, record_buffer, extra_frames_in_record_buffer);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
rb_raise(rb_eArgError, "Unexpected value for sample_type: %d", type);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Idea: Should we release the global vm lock (GVL) after we get the data from `rb_profile_frames`? That way other Ruby threads
|
|
174
|
+
// could continue making progress while the sample was ingested into the profile.
|
|
175
|
+
//
|
|
176
|
+
// Other things to take into consideration if we go in that direction:
|
|
177
|
+
// * Is it safe to call `rb_profile_frame_...` methods on things from the `stack_buffer` without the GVL acquired?
|
|
178
|
+
// * We need to make `VALUE` references in the `stack_buffer` visible to the Ruby GC
|
|
179
|
+
// * Should we move this into a different thread entirely?
|
|
180
|
+
// * If we don't move it into a different thread, does releasing the GVL on a Ruby thread mean that we're introducing
|
|
181
|
+
// a new thread switch point where there previously was none?
|
|
182
|
+
//
|
|
183
|
+
// ---
|
|
184
|
+
//
|
|
185
|
+
// Why the weird extra record_buffer and extra_frames_in_record_buffer?
|
|
186
|
+
// The answer is: to support both sample_thread() and sample_thread_in_gc().
|
|
187
|
+
//
|
|
188
|
+
// For sample_thread(), buffer == record_buffer and extra_frames_in_record_buffer == 0, so it's a no-op.
|
|
189
|
+
// For sample_thread_in_gc(), the buffer is a special buffer that is the same as the record_buffer, but with every
|
|
190
|
+
// pointer shifted forward extra_frames_in_record_buffer elements, so that the caller can actually inject those extra
|
|
191
|
+
// frames, and this function doesn't have to care about it.
|
|
192
|
+
static void sample_thread_internal(
|
|
193
|
+
VALUE thread,
|
|
194
|
+
sampling_buffer* buffer,
|
|
195
|
+
VALUE recorder_instance,
|
|
196
|
+
ddog_Slice_i64 metric_values,
|
|
197
|
+
ddog_Slice_label labels,
|
|
198
|
+
sampling_buffer *record_buffer,
|
|
199
|
+
int extra_frames_in_record_buffer
|
|
200
|
+
) {
|
|
97
201
|
int captured_frames = ddtrace_rb_profile_frames(
|
|
98
202
|
thread,
|
|
99
203
|
0 /* stack starting depth */,
|
|
@@ -103,15 +207,17 @@ void sample_thread(VALUE thread, sampling_buffer* buffer, VALUE recorder_instanc
|
|
|
103
207
|
buffer->is_ruby_frame
|
|
104
208
|
);
|
|
105
209
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
210
|
+
if (captured_frames == PLACEHOLDER_STACK_IN_NATIVE_CODE) {
|
|
211
|
+
record_placeholder_stack_in_native_code(
|
|
212
|
+
buffer,
|
|
213
|
+
recorder_instance,
|
|
214
|
+
metric_values,
|
|
215
|
+
labels,
|
|
216
|
+
record_buffer,
|
|
217
|
+
extra_frames_in_record_buffer
|
|
218
|
+
);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
115
221
|
|
|
116
222
|
// Ruby does not give us path and line number for methods implemented using native code.
|
|
117
223
|
// The convention in Kernel#caller_locations is to instead use the path and line number of the first Ruby frame
|
|
@@ -121,11 +227,6 @@ void sample_thread(VALUE thread, sampling_buffer* buffer, VALUE recorder_instanc
|
|
|
121
227
|
VALUE last_ruby_frame = Qnil;
|
|
122
228
|
int last_ruby_line = 0;
|
|
123
229
|
|
|
124
|
-
if (captured_frames == PLACEHOLDER_STACK_IN_NATIVE_CODE) {
|
|
125
|
-
record_placeholder_stack_in_native_code(recorder_instance, metric_values, labels);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
230
|
for (int i = captured_frames - 1; i >= 0; i--) {
|
|
130
231
|
VALUE name, filename;
|
|
131
232
|
int line;
|
|
@@ -157,15 +258,13 @@ void sample_thread(VALUE thread, sampling_buffer* buffer, VALUE recorder_instanc
|
|
|
157
258
|
name = NIL_P(name) ? missing_string : name;
|
|
158
259
|
filename = NIL_P(filename) ? missing_string : filename;
|
|
159
260
|
|
|
160
|
-
buffer->lines[i] = (
|
|
161
|
-
.function = (
|
|
261
|
+
buffer->lines[i] = (ddog_Line) {
|
|
262
|
+
.function = (ddog_Function) {
|
|
162
263
|
.name = char_slice_from_ruby_string(name),
|
|
163
264
|
.filename = char_slice_from_ruby_string(filename)
|
|
164
265
|
},
|
|
165
266
|
.line = line,
|
|
166
267
|
};
|
|
167
|
-
|
|
168
|
-
buffer->locations[i] = (ddprof_ffi_Location) {.lines = (ddprof_ffi_Slice_line) {.ptr = &buffer->lines[i], .len = 1}};
|
|
169
268
|
}
|
|
170
269
|
|
|
171
270
|
// Used below; since we want to stack-allocate this, we must do it here rather than in maybe_add_placeholder_frames_omitted
|
|
@@ -180,8 +279,8 @@ void sample_thread(VALUE thread, sampling_buffer* buffer, VALUE recorder_instanc
|
|
|
180
279
|
|
|
181
280
|
record_sample(
|
|
182
281
|
recorder_instance,
|
|
183
|
-
(
|
|
184
|
-
.locations = (
|
|
282
|
+
(ddog_Sample) {
|
|
283
|
+
.locations = (ddog_Slice_location) {.ptr = record_buffer->locations, .len = captured_frames + extra_frames_in_record_buffer},
|
|
185
284
|
.values = metric_values,
|
|
186
285
|
.labels = labels,
|
|
187
286
|
}
|
|
@@ -201,10 +300,10 @@ static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer*
|
|
|
201
300
|
|
|
202
301
|
// Important note: `frames_omitted_message` MUST have a lifetime that is at least as long as the call to
|
|
203
302
|
// `record_sample`. So be careful where it gets allocated. (We do have tests for this, at least!)
|
|
204
|
-
buffer->lines[buffer->max_frames - 1] = (
|
|
205
|
-
.function = (
|
|
206
|
-
.name =
|
|
207
|
-
.filename = ((
|
|
303
|
+
buffer->lines[buffer->max_frames - 1] = (ddog_Line) {
|
|
304
|
+
.function = (ddog_Function) {
|
|
305
|
+
.name = DDOG_CHARSLICE_C(""),
|
|
306
|
+
.filename = ((ddog_CharSlice) {.ptr = frames_omitted_message, .len = strlen(frames_omitted_message)})
|
|
208
307
|
},
|
|
209
308
|
.line = 0,
|
|
210
309
|
};
|
|
@@ -230,21 +329,26 @@ static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer*
|
|
|
230
329
|
//
|
|
231
330
|
// To give customers visibility into these threads, rather than reporting an empty stack, we replace the empty stack
|
|
232
331
|
// with one containing a placeholder frame, so that these threads are properly represented in the UX.
|
|
233
|
-
static void record_placeholder_stack_in_native_code(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
332
|
+
static void record_placeholder_stack_in_native_code(
|
|
333
|
+
sampling_buffer* buffer,
|
|
334
|
+
VALUE recorder_instance,
|
|
335
|
+
ddog_Slice_i64 metric_values,
|
|
336
|
+
ddog_Slice_label labels,
|
|
337
|
+
sampling_buffer *record_buffer,
|
|
338
|
+
int extra_frames_in_record_buffer
|
|
339
|
+
) {
|
|
340
|
+
buffer->lines[0] = (ddog_Line) {
|
|
341
|
+
.function = (ddog_Function) {
|
|
342
|
+
.name = DDOG_CHARSLICE_C(""),
|
|
343
|
+
.filename = DDOG_CHARSLICE_C("In native code")
|
|
238
344
|
},
|
|
239
345
|
.line = 0
|
|
240
346
|
};
|
|
241
|
-
ddprof_ffi_Location placeholder_stack_in_native_code_location =
|
|
242
|
-
{.lines = (ddprof_ffi_Slice_line) {.ptr = &placeholder_stack_in_native_code_line, .len = 1}};
|
|
243
347
|
|
|
244
348
|
record_sample(
|
|
245
349
|
recorder_instance,
|
|
246
|
-
(
|
|
247
|
-
.locations = (
|
|
350
|
+
(ddog_Sample) {
|
|
351
|
+
.locations = (ddog_Slice_location) {.ptr = record_buffer->locations, .len = 1 + extra_frames_in_record_buffer},
|
|
248
352
|
.values = metric_values,
|
|
249
353
|
.labels = labels,
|
|
250
354
|
}
|
|
@@ -263,8 +367,14 @@ sampling_buffer *sampling_buffer_new(unsigned int max_frames) {
|
|
|
263
367
|
buffer->stack_buffer = ruby_xcalloc(max_frames, sizeof(VALUE));
|
|
264
368
|
buffer->lines_buffer = ruby_xcalloc(max_frames, sizeof(int));
|
|
265
369
|
buffer->is_ruby_frame = ruby_xcalloc(max_frames, sizeof(bool));
|
|
266
|
-
buffer->locations = ruby_xcalloc(max_frames, sizeof(
|
|
267
|
-
buffer->lines = ruby_xcalloc(max_frames, sizeof(
|
|
370
|
+
buffer->locations = ruby_xcalloc(max_frames, sizeof(ddog_Location));
|
|
371
|
+
buffer->lines = ruby_xcalloc(max_frames, sizeof(ddog_Line));
|
|
372
|
+
|
|
373
|
+
// Currently we have a 1-to-1 correspondence between lines and locations, so we just initialize the locations once
|
|
374
|
+
// here and then only mutate the contents of the lines.
|
|
375
|
+
for (unsigned int i = 0; i < max_frames; i++) {
|
|
376
|
+
buffer->locations[i] = (ddog_Location) {.lines = (ddog_Slice_line) {.ptr = &buffer->lines[i], .len = 1}};
|
|
377
|
+
}
|
|
268
378
|
|
|
269
379
|
return buffer;
|
|
270
380
|
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <
|
|
3
|
+
#include <datadog/profiling.h>
|
|
4
4
|
|
|
5
5
|
typedef struct sampling_buffer sampling_buffer;
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
typedef enum { SAMPLE_REGULAR, SAMPLE_IN_GC } sample_type;
|
|
8
|
+
|
|
9
|
+
void sample_thread(
|
|
10
|
+
VALUE thread,
|
|
11
|
+
sampling_buffer* buffer,
|
|
12
|
+
VALUE recorder_instance,
|
|
13
|
+
ddog_Slice_i64 metric_values,
|
|
14
|
+
ddog_Slice_label labels,
|
|
15
|
+
sample_type type
|
|
16
|
+
);
|
|
8
17
|
sampling_buffer *sampling_buffer_new(unsigned int max_frames);
|
|
9
18
|
void sampling_buffer_free(sampling_buffer *buffer);
|
|
@@ -77,6 +77,10 @@ def add_compiler_flag(flag)
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
# Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
|
|
81
|
+
# But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
|
|
82
|
+
add_compiler_flag '-Werror' if ENV['CI'] == 'true'
|
|
83
|
+
|
|
80
84
|
# Older gcc releases may not default to C99 and we need to ask for this. This is also used:
|
|
81
85
|
# * by upstream Ruby -- search for gnu99 in the codebase
|
|
82
86
|
# * by msgpack, another ddtrace dependency
|
|
@@ -122,9 +126,15 @@ end
|
|
|
122
126
|
# On older Rubies, there was no struct rb_native_thread. See private_vm_api_acccess.c for details.
|
|
123
127
|
$defs << '-DNO_RB_NATIVE_THREAD' if RUBY_VERSION < '3.2'
|
|
124
128
|
|
|
129
|
+
# On older Rubies, there was no tid member in the internal thread structure
|
|
130
|
+
$defs << '-DNO_THREAD_TID' if RUBY_VERSION < '3.1'
|
|
131
|
+
|
|
125
132
|
# On older Rubies, we need to use a backported version of this function. See private_vm_api_access.h for details.
|
|
126
133
|
$defs << '-DUSE_BACKPORTED_RB_PROFILE_FRAME_METHOD_NAME' if RUBY_VERSION < '3'
|
|
127
134
|
|
|
135
|
+
# On older Rubies, there are no Ractors
|
|
136
|
+
$defs << '-DNO_RACTORS' if RUBY_VERSION < '3'
|
|
137
|
+
|
|
128
138
|
# On older Rubies, we need to use rb_thread_t instead of rb_execution_context_t
|
|
129
139
|
$defs << '-DUSE_THREAD_INSTEAD_OF_EXECUTION_CONTEXT' if RUBY_VERSION < '2.5'
|
|
130
140
|
|
|
@@ -152,7 +162,7 @@ end
|
|
|
152
162
|
ENV['PKG_CONFIG_PATH'] = "#{ENV['PKG_CONFIG_PATH']}:#{Libdatadog.pkgconfig_folder}"
|
|
153
163
|
Logging.message(" [ddtrace] PKG_CONFIG_PATH set to #{ENV['PKG_CONFIG_PATH'].inspect}\n")
|
|
154
164
|
|
|
155
|
-
unless pkg_config('
|
|
165
|
+
unless pkg_config('datadog_profiling_with_rpath')
|
|
156
166
|
skip_building_extension!(
|
|
157
167
|
if Datadog::Profiling::NativeExtensionHelpers::Supported.pkg_config_missing?
|
|
158
168
|
Datadog::Profiling::NativeExtensionHelpers::Supported::PKG_CONFIG_IS_MISSING
|