ddtrace 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -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 +44 -18
- data/lib/datadog/appsec/event.rb +8 -4
- data/lib/datadog/core/configuration/components.rb +20 -14
- data/lib/datadog/core/configuration/settings.rb +59 -7
- 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/client_ip.rb +11 -0
- data/lib/datadog/tracing/configuration/ext.rb +3 -1
- 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 +15 -7
- 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
|