datadog 2.3.0 → 2.4.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 +37 -1
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +10 -22
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +148 -30
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
- data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +580 -29
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +9 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
- data/ext/datadog_profiling_native_extension/extconf.rb +38 -21
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +20 -6
- data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +52 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
- data/ext/libdatadog_api/crashtracker.c +20 -18
- data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
- data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
- data/lib/datadog/appsec/component.rb +29 -8
- data/lib/datadog/appsec/configuration/settings.rb +2 -2
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +18 -15
- data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
- data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
- data/lib/datadog/appsec/processor.rb +36 -37
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +4 -3
- data/lib/datadog/core/configuration/settings.rb +84 -5
- data/lib/datadog/core/crashtracking/component.rb +1 -1
- data/lib/datadog/core/environment/execution.rb +5 -5
- data/lib/datadog/core/metrics/client.rb +7 -0
- data/lib/datadog/core/rate_limiter.rb +183 -0
- data/lib/datadog/core/remote/client/capabilities.rb +4 -3
- data/lib/datadog/core/remote/component.rb +4 -2
- data/lib/datadog/core/remote/negotiation.rb +4 -4
- data/lib/datadog/core/remote/tie.rb +2 -0
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +2 -0
- data/lib/datadog/core/telemetry/event.rb +12 -7
- data/lib/datadog/core/telemetry/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +50 -14
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/di/code_tracker.rb +168 -0
- data/lib/datadog/di/configuration/settings.rb +163 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/error.rb +31 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/probe.rb +133 -0
- data/lib/datadog/di/probe_builder.rb +41 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +193 -0
- data/lib/datadog/di.rb +14 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
- data/lib/datadog/profiling/collectors/info.rb +12 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +26 -0
- data/lib/datadog/profiling/component.rb +20 -4
- data/lib/datadog/profiling/http_transport.rb +6 -1
- data/lib/datadog/profiling/scheduler.rb +2 -0
- data/lib/datadog/profiling/stack_recorder.rb +3 -0
- data/lib/datadog/single_step_instrument.rb +12 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
- data/lib/datadog/tracing/distributed/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/ext.rb +2 -0
- data/lib/datadog/tracing/remote.rb +5 -2
- data/lib/datadog/tracing/sampling/matcher.rb +6 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +2 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +14 -12
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +25 -8
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -20,16 +20,9 @@ struct sampling_buffer {
|
|
20
20
|
frame_info *stack_buffer;
|
21
21
|
}; // Note: typedef'd in the header to sampling_buffer
|
22
22
|
|
23
|
-
static VALUE _native_sample(
|
24
|
-
|
25
|
-
|
26
|
-
VALUE recorder_instance,
|
27
|
-
VALUE metric_values_hash,
|
28
|
-
VALUE labels_array,
|
29
|
-
VALUE numeric_labels_array,
|
30
|
-
VALUE max_frames,
|
31
|
-
VALUE in_gc
|
32
|
-
);
|
23
|
+
static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
24
|
+
static VALUE native_sample_do(VALUE args);
|
25
|
+
static VALUE native_sample_ensure(VALUE args);
|
33
26
|
static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size);
|
34
27
|
static void record_placeholder_stack_in_native_code(VALUE recorder_instance, sample_values values, sample_labels labels);
|
35
28
|
static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_CharSlice *filename_slice);
|
@@ -45,24 +38,42 @@ void collectors_stack_init(VALUE profiling_module) {
|
|
45
38
|
// Hosts methods used for testing the native code using RSpec
|
46
39
|
VALUE testing_module = rb_define_module_under(collectors_stack_class, "Testing");
|
47
40
|
|
48
|
-
rb_define_singleton_method(testing_module, "_native_sample", _native_sample,
|
41
|
+
rb_define_singleton_method(testing_module, "_native_sample", _native_sample, -1);
|
49
42
|
|
50
43
|
missing_string = rb_str_new2("");
|
51
44
|
rb_global_variable(&missing_string);
|
52
45
|
}
|
53
46
|
|
47
|
+
struct native_sample_args {
|
48
|
+
VALUE in_gc;
|
49
|
+
VALUE recorder_instance;
|
50
|
+
sample_values values;
|
51
|
+
sample_labels labels;
|
52
|
+
VALUE thread;
|
53
|
+
ddog_prof_Location *locations;
|
54
|
+
sampling_buffer *buffer;
|
55
|
+
};
|
56
|
+
|
54
57
|
// This method exists only to enable testing Datadog::Profiling::Collectors::Stack behavior using RSpec.
|
55
58
|
// It SHOULD NOT be used for other purposes.
|
56
|
-
static VALUE _native_sample(
|
57
|
-
|
58
|
-
VALUE thread
|
59
|
-
VALUE recorder_instance
|
60
|
-
VALUE metric_values_hash
|
61
|
-
VALUE labels_array
|
62
|
-
VALUE numeric_labels_array
|
63
|
-
VALUE
|
64
|
-
|
65
|
-
)
|
59
|
+
static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
|
60
|
+
// Positional args
|
61
|
+
VALUE thread;
|
62
|
+
VALUE recorder_instance;
|
63
|
+
VALUE metric_values_hash;
|
64
|
+
VALUE labels_array;
|
65
|
+
VALUE numeric_labels_array;
|
66
|
+
VALUE options;
|
67
|
+
|
68
|
+
rb_scan_args(argc, argv, "5:", &thread, &recorder_instance, &metric_values_hash, &labels_array, &numeric_labels_array, &options);
|
69
|
+
|
70
|
+
if (options == Qnil) options = rb_hash_new();
|
71
|
+
|
72
|
+
// Optional keyword args
|
73
|
+
VALUE max_frames = rb_hash_lookup2(options, ID2SYM(rb_intern("max_frames")), INT2NUM(400));
|
74
|
+
VALUE in_gc = rb_hash_lookup2(options, ID2SYM(rb_intern("in_gc")), Qfalse);
|
75
|
+
VALUE is_gvl_waiting_state = rb_hash_lookup2(options, ID2SYM(rb_intern("is_gvl_waiting_state")), Qfalse);
|
76
|
+
|
66
77
|
ENFORCE_TYPE(metric_values_hash, T_HASH);
|
67
78
|
ENFORCE_TYPE(labels_array, T_ARRAY);
|
68
79
|
ENFORCE_TYPE(numeric_labels_array, T_ARRAY);
|
@@ -105,33 +116,54 @@ static VALUE _native_sample(
|
|
105
116
|
};
|
106
117
|
}
|
107
118
|
|
108
|
-
int max_frames_requested = NUM2INT(max_frames);
|
109
|
-
if (max_frames_requested < 0) rb_raise(rb_eArgError, "Invalid max_frames: value must not be negative");
|
119
|
+
int max_frames_requested = sampling_buffer_check_max_frames(NUM2INT(max_frames));
|
110
120
|
|
111
121
|
ddog_prof_Location *locations = ruby_xcalloc(max_frames_requested, sizeof(ddog_prof_Location));
|
112
122
|
sampling_buffer *buffer = sampling_buffer_new(max_frames_requested, locations);
|
113
123
|
|
114
124
|
ddog_prof_Slice_Label slice_labels = {.ptr = labels, .len = labels_count};
|
115
125
|
|
116
|
-
|
126
|
+
struct native_sample_args args_struct = {
|
127
|
+
.in_gc = in_gc,
|
128
|
+
.recorder_instance = recorder_instance,
|
129
|
+
.values = values,
|
130
|
+
.labels = (sample_labels) {.labels = slice_labels, .state_label = state_label, .is_gvl_waiting_state = is_gvl_waiting_state == Qtrue},
|
131
|
+
.thread = thread,
|
132
|
+
.locations = locations,
|
133
|
+
.buffer = buffer,
|
134
|
+
};
|
135
|
+
|
136
|
+
return rb_ensure(native_sample_do, (VALUE) &args_struct, native_sample_ensure, (VALUE) &args_struct);
|
137
|
+
}
|
138
|
+
|
139
|
+
static VALUE native_sample_do(VALUE args) {
|
140
|
+
struct native_sample_args *args_struct = (struct native_sample_args *) args;
|
141
|
+
|
142
|
+
if (args_struct->in_gc == Qtrue) {
|
117
143
|
record_placeholder_stack(
|
118
|
-
recorder_instance,
|
119
|
-
values,
|
120
|
-
|
144
|
+
args_struct->recorder_instance,
|
145
|
+
args_struct->values,
|
146
|
+
args_struct->labels,
|
121
147
|
DDOG_CHARSLICE_C("Garbage Collection")
|
122
148
|
);
|
123
149
|
} else {
|
124
150
|
sample_thread(
|
125
|
-
thread,
|
126
|
-
buffer,
|
127
|
-
recorder_instance,
|
128
|
-
values,
|
129
|
-
|
151
|
+
args_struct->thread,
|
152
|
+
args_struct->buffer,
|
153
|
+
args_struct->recorder_instance,
|
154
|
+
args_struct->values,
|
155
|
+
args_struct->labels
|
130
156
|
);
|
131
157
|
}
|
132
158
|
|
133
|
-
|
134
|
-
|
159
|
+
return Qtrue;
|
160
|
+
}
|
161
|
+
|
162
|
+
static VALUE native_sample_ensure(VALUE args) {
|
163
|
+
struct native_sample_args *args_struct = (struct native_sample_args *) args;
|
164
|
+
|
165
|
+
ruby_xfree(args_struct->locations);
|
166
|
+
sampling_buffer_free(args_struct->buffer);
|
135
167
|
|
136
168
|
return Qtrue;
|
137
169
|
}
|
@@ -185,11 +217,17 @@ void sample_thread(
|
|
185
217
|
ddog_prof_Label *state_label = labels.state_label;
|
186
218
|
bool cpu_or_wall_sample = values.cpu_or_wall_samples > 0;
|
187
219
|
bool has_cpu_time = cpu_or_wall_sample && values.cpu_time_ns > 0;
|
188
|
-
|
220
|
+
// Note: In theory, a cpu_or_wall_sample should always have some wall-time. In practice, the first sample for a thread
|
221
|
+
// will be zero, as well as if the system clock does something weird. Thus, at some point we had values.wall_time_ns > 0
|
222
|
+
// here, but >= 0 makes this easier to understand/debug.
|
223
|
+
bool only_wall_time = cpu_or_wall_sample && values.cpu_time_ns == 0 && values.wall_time_ns >= 0;
|
189
224
|
|
190
225
|
if (cpu_or_wall_sample && state_label == NULL) rb_raise(rb_eRuntimeError, "BUG: Unexpected missing state_label");
|
191
226
|
|
192
|
-
if (has_cpu_time)
|
227
|
+
if (has_cpu_time) {
|
228
|
+
state_label->str = DDOG_CHARSLICE_C("had cpu");
|
229
|
+
if (labels.is_gvl_waiting_state) rb_raise(rb_eRuntimeError, "BUG: Unexpected combination of cpu-time with is_gvl_waiting");
|
230
|
+
}
|
193
231
|
|
194
232
|
for (int i = captured_frames - 1; i >= 0; i--) {
|
195
233
|
VALUE name, filename;
|
@@ -219,12 +257,15 @@ void sample_thread(
|
|
219
257
|
bool top_of_the_stack = i == 0;
|
220
258
|
|
221
259
|
// When there's only wall-time in a sample, this means that the thread was not active in the sampled period.
|
222
|
-
//
|
223
|
-
// We try to categorize what it was doing based on what we observe at the top of the stack. This is a very rough
|
224
|
-
// approximation, and in the future we hope to replace this with a more accurate approach (such as using the
|
225
|
-
// GVL instrumentation API.)
|
226
260
|
if (top_of_the_stack && only_wall_time) {
|
227
|
-
|
261
|
+
// Did the caller already provide the state?
|
262
|
+
if (labels.is_gvl_waiting_state) {
|
263
|
+
state_label->str = DDOG_CHARSLICE_C("waiting for gvl");
|
264
|
+
|
265
|
+
// Otherwise, we try to categorize what the thread was doing based on what we observe at the top of the stack. This is a very rough
|
266
|
+
// approximation, and in the future we hope to replace this with a more accurate approach (such as using the
|
267
|
+
// GVL instrumentation API.)
|
268
|
+
} else if (!buffer->stack_buffer[i].is_ruby_frame) {
|
228
269
|
// We know that known versions of Ruby implement these using native code; thus if we find a method with the
|
229
270
|
// same name that is not native code, we ignore it, as it's probably a user method that coincidentally
|
230
271
|
// has the same name. Thus, even though "matching just by method name" is kinda weak,
|
@@ -259,10 +300,8 @@ void sample_thread(
|
|
259
300
|
}
|
260
301
|
|
261
302
|
buffer->locations[i] = (ddog_prof_Location) {
|
262
|
-
.
|
263
|
-
|
264
|
-
.filename = filename_slice,
|
265
|
-
},
|
303
|
+
.mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
|
304
|
+
.function = (ddog_prof_Function) {.name = name_slice, .filename = filename_slice},
|
266
305
|
.line = line,
|
267
306
|
};
|
268
307
|
}
|
@@ -300,7 +339,9 @@ static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_Char
|
|
300
339
|
// Check filename doesn't end with ".rb"; templates are usually along the lines of .html.erb/.html.haml/...
|
301
340
|
if (filename_slice->len < 3 || memcmp(filename_slice->ptr + filename_slice->len - 3, ".rb", 3) == 0) return;
|
302
341
|
|
303
|
-
|
342
|
+
if (name_slice->len > 1024) return;
|
343
|
+
|
344
|
+
int pos = ((int) name_slice->len) - 1;
|
304
345
|
|
305
346
|
// Let's match on something__number_number:
|
306
347
|
// Find start of id suffix from the end...
|
@@ -338,6 +379,7 @@ static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer*
|
|
338
379
|
ddog_CharSlice function_name = DDOG_CHARSLICE_C("");
|
339
380
|
ddog_CharSlice function_filename = {.ptr = frames_omitted_message, .len = strlen(frames_omitted_message)};
|
340
381
|
buffer->locations[buffer->max_frames - 1] = (ddog_prof_Location) {
|
382
|
+
.mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
|
341
383
|
.function = (ddog_prof_Function) {.name = function_name, .filename = function_filename},
|
342
384
|
.line = 0,
|
343
385
|
};
|
@@ -384,6 +426,7 @@ void record_placeholder_stack(
|
|
384
426
|
ddog_CharSlice placeholder_stack
|
385
427
|
) {
|
386
428
|
ddog_prof_Location placeholder_location = {
|
429
|
+
.mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
|
387
430
|
.function = {.name = DDOG_CHARSLICE_C(""), .filename = placeholder_stack},
|
388
431
|
.line = 0,
|
389
432
|
};
|