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
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
#include "libdatadog_helpers.h"
|
|
8
8
|
#include "ruby_helpers.h"
|
|
9
9
|
|
|
10
|
-
// Used to wrap a
|
|
10
|
+
// Used to wrap a ddog_Profile in a Ruby object and expose Ruby-level serialization APIs
|
|
11
11
|
// This file implements the native bits of the Datadog::Profiling::StackRecorder class
|
|
12
12
|
|
|
13
13
|
// ---
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
// 2. The thread that serializes and reports profiles, let's call it the **serializer thread**. We enforce that there
|
|
25
25
|
// cannot be more than one thread attempting to serialize profiles at a time.
|
|
26
26
|
//
|
|
27
|
-
// If both the sampler and serializer threads are trying to access the same `
|
|
27
|
+
// If both the sampler and serializer threads are trying to access the same `ddog_Profile` in parallel, we will
|
|
28
28
|
// have a concurrency issue. Thus, the StackRecorder has an added mechanism to avoid this.
|
|
29
29
|
//
|
|
30
30
|
// As an additional constraint, the **sampler thread** has absolute priority and must never block while
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
//
|
|
33
33
|
// ### The solution: Keep two profiles at the same time
|
|
34
34
|
//
|
|
35
|
-
// To solve for the constraints above, the StackRecorder keeps two `
|
|
35
|
+
// To solve for the constraints above, the StackRecorder keeps two `ddog_Profile` profile instances inside itself.
|
|
36
36
|
// They are called the `slot_one_profile` and `slot_two_profile`.
|
|
37
37
|
//
|
|
38
38
|
// Each profile is paired with its own mutex. `slot_one_profile` is protected by `slot_one_mutex` and `slot_two_profile`
|
|
@@ -135,10 +135,10 @@ static VALUE stack_recorder_class = Qnil;
|
|
|
135
135
|
// Contains native state for each instance
|
|
136
136
|
struct stack_recorder_state {
|
|
137
137
|
pthread_mutex_t slot_one_mutex;
|
|
138
|
-
|
|
138
|
+
ddog_Profile *slot_one_profile;
|
|
139
139
|
|
|
140
140
|
pthread_mutex_t slot_two_mutex;
|
|
141
|
-
|
|
141
|
+
ddog_Profile *slot_two_profile;
|
|
142
142
|
|
|
143
143
|
short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
|
|
144
144
|
};
|
|
@@ -146,7 +146,7 @@ struct stack_recorder_state {
|
|
|
146
146
|
// Used to return a pair of values from sampler_lock_active_profile()
|
|
147
147
|
struct active_slot_pair {
|
|
148
148
|
pthread_mutex_t *mutex;
|
|
149
|
-
|
|
149
|
+
ddog_Profile *profile;
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
struct call_serialize_without_gvl_arguments {
|
|
@@ -154,8 +154,8 @@ struct call_serialize_without_gvl_arguments {
|
|
|
154
154
|
struct stack_recorder_state *state;
|
|
155
155
|
|
|
156
156
|
// Set by callee
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
ddog_Profile *profile;
|
|
158
|
+
ddog_SerializeResult result;
|
|
159
159
|
|
|
160
160
|
// Set by both
|
|
161
161
|
bool serialize_ran;
|
|
@@ -164,15 +164,16 @@ struct call_serialize_without_gvl_arguments {
|
|
|
164
164
|
static VALUE _native_new(VALUE klass);
|
|
165
165
|
static void stack_recorder_typed_data_free(void *data);
|
|
166
166
|
static VALUE _native_serialize(VALUE self, VALUE recorder_instance);
|
|
167
|
-
static VALUE ruby_time_from(
|
|
167
|
+
static VALUE ruby_time_from(ddog_Timespec ddprof_time);
|
|
168
168
|
static void *call_serialize_without_gvl(void *call_args);
|
|
169
169
|
static struct active_slot_pair sampler_lock_active_profile();
|
|
170
170
|
static void sampler_unlock_active_profile(struct active_slot_pair active_slot);
|
|
171
|
-
static
|
|
171
|
+
static ddog_Profile *serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state, ddog_Timespec start_timestamp_for_next_profile);
|
|
172
172
|
static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
173
173
|
static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
174
174
|
static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
175
175
|
static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot);
|
|
176
|
+
static ddog_Timespec time_now();
|
|
176
177
|
|
|
177
178
|
void stack_recorder_init(VALUE profiling_module) {
|
|
178
179
|
stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
|
|
@@ -199,7 +200,7 @@ void stack_recorder_init(VALUE profiling_module) {
|
|
|
199
200
|
ruby_time_from_id = rb_intern_const("ruby_time_from");
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
// This structure is used to define a Ruby object that stores a pointer to a
|
|
203
|
+
// This structure is used to define a Ruby object that stores a pointer to a ddog_Profile instance
|
|
203
204
|
// See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
|
|
204
205
|
static const rb_data_type_t stack_recorder_typed_data = {
|
|
205
206
|
.wrap_struct_name = "Datadog::Profiling::StackRecorder",
|
|
@@ -214,7 +215,7 @@ static const rb_data_type_t stack_recorder_typed_data = {
|
|
|
214
215
|
static VALUE _native_new(VALUE klass) {
|
|
215
216
|
struct stack_recorder_state *state = ruby_xcalloc(1, sizeof(struct stack_recorder_state));
|
|
216
217
|
|
|
217
|
-
|
|
218
|
+
ddog_Slice_value_type sample_types = {.ptr = enabled_value_types, .len = ENABLED_VALUE_TYPES_COUNT};
|
|
218
219
|
|
|
219
220
|
state->slot_one_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
|
|
220
221
|
state->slot_two_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
|
|
@@ -227,8 +228,8 @@ static VALUE _native_new(VALUE klass) {
|
|
|
227
228
|
|
|
228
229
|
// Note: Don't raise exceptions after this point, since it'll lead to libdatadog memory leaking!
|
|
229
230
|
|
|
230
|
-
state->slot_one_profile =
|
|
231
|
-
state->slot_two_profile =
|
|
231
|
+
state->slot_one_profile = ddog_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
|
|
232
|
+
state->slot_two_profile = ddog_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
|
|
232
233
|
|
|
233
234
|
return TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
|
|
234
235
|
}
|
|
@@ -237,10 +238,10 @@ static void stack_recorder_typed_data_free(void *state_ptr) {
|
|
|
237
238
|
struct stack_recorder_state *state = (struct stack_recorder_state *) state_ptr;
|
|
238
239
|
|
|
239
240
|
pthread_mutex_destroy(&state->slot_one_mutex);
|
|
240
|
-
|
|
241
|
+
ddog_Profile_free(state->slot_one_profile);
|
|
241
242
|
|
|
242
243
|
pthread_mutex_destroy(&state->slot_two_mutex);
|
|
243
|
-
|
|
244
|
+
ddog_Profile_free(state->slot_two_profile);
|
|
244
245
|
|
|
245
246
|
ruby_xfree(state);
|
|
246
247
|
}
|
|
@@ -267,33 +268,33 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
|
267
268
|
rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, NULL /* No interruption function needed in this case */, NULL /* Not needed */);
|
|
268
269
|
}
|
|
269
270
|
|
|
270
|
-
|
|
271
|
+
ddog_SerializeResult serialized_profile = args.result;
|
|
271
272
|
|
|
272
|
-
if (serialized_profile.tag ==
|
|
273
|
+
if (serialized_profile.tag == DDOG_SERIALIZE_RESULT_ERR) {
|
|
273
274
|
VALUE err_details = ruby_string_from_vec_u8(serialized_profile.err);
|
|
274
|
-
|
|
275
|
+
ddog_SerializeResult_drop(serialized_profile);
|
|
275
276
|
return rb_ary_new_from_args(2, error_symbol, err_details);
|
|
276
277
|
}
|
|
277
278
|
|
|
278
279
|
VALUE encoded_pprof = ruby_string_from_vec_u8(serialized_profile.ok.buffer);
|
|
279
280
|
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
ddog_Timespec ddprof_start = serialized_profile.ok.start;
|
|
282
|
+
ddog_Timespec ddprof_finish = serialized_profile.ok.end;
|
|
282
283
|
|
|
283
284
|
// Clean up libdatadog object to avoid leaking in case ruby_time_from raises an exception
|
|
284
|
-
|
|
285
|
+
ddog_SerializeResult_drop(serialized_profile);
|
|
285
286
|
|
|
286
287
|
VALUE start = ruby_time_from(ddprof_start);
|
|
287
288
|
VALUE finish = ruby_time_from(ddprof_finish);
|
|
288
289
|
|
|
289
|
-
if (!
|
|
290
|
+
if (!ddog_Profile_reset(args.profile, NULL /* start_time is optional */ )) {
|
|
290
291
|
return rb_ary_new_from_args(2, error_symbol, rb_str_new_cstr("Failed to reset profile"));
|
|
291
292
|
}
|
|
292
293
|
|
|
293
294
|
return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(3, start, finish, encoded_pprof));
|
|
294
295
|
}
|
|
295
296
|
|
|
296
|
-
static VALUE ruby_time_from(
|
|
297
|
+
static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
|
|
297
298
|
#ifndef NO_RB_TIME_TIMESPEC_NEW // Modern Rubies
|
|
298
299
|
const int utc = INT_MAX - 1; // From Ruby sources
|
|
299
300
|
struct timespec time = {.tv_sec = ddprof_time.seconds, .tv_nsec = ddprof_time.nanoseconds};
|
|
@@ -303,13 +304,13 @@ static VALUE ruby_time_from(ddprof_ffi_Timespec ddprof_time) {
|
|
|
303
304
|
#endif
|
|
304
305
|
}
|
|
305
306
|
|
|
306
|
-
void record_sample(VALUE recorder_instance,
|
|
307
|
+
void record_sample(VALUE recorder_instance, ddog_Sample sample) {
|
|
307
308
|
struct stack_recorder_state *state;
|
|
308
309
|
TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
|
|
309
310
|
|
|
310
311
|
struct active_slot_pair active_slot = sampler_lock_active_profile(state);
|
|
311
312
|
|
|
312
|
-
|
|
313
|
+
ddog_Profile_add(active_slot.profile, sample);
|
|
313
314
|
|
|
314
315
|
sampler_unlock_active_profile(active_slot);
|
|
315
316
|
}
|
|
@@ -317,8 +318,10 @@ void record_sample(VALUE recorder_instance, ddprof_ffi_Sample sample) {
|
|
|
317
318
|
static void *call_serialize_without_gvl(void *call_args) {
|
|
318
319
|
struct call_serialize_without_gvl_arguments *args = (struct call_serialize_without_gvl_arguments *) call_args;
|
|
319
320
|
|
|
320
|
-
|
|
321
|
-
|
|
321
|
+
ddog_Timespec finish_timestamp = time_now();
|
|
322
|
+
|
|
323
|
+
args->profile = serializer_flip_active_and_inactive_slots(args->state, finish_timestamp);
|
|
324
|
+
args->result = ddog_Profile_serialize(args->profile, &finish_timestamp, NULL /* duration_nanos is optional */);
|
|
322
325
|
args->serialize_ran = true;
|
|
323
326
|
|
|
324
327
|
return NULL; // Unused
|
|
@@ -357,7 +360,7 @@ static void sampler_unlock_active_profile(struct active_slot_pair active_slot) {
|
|
|
357
360
|
if (error != 0) rb_syserr_fail(error, "Unexpected failure in sampler_unlock_active_profile");
|
|
358
361
|
}
|
|
359
362
|
|
|
360
|
-
static
|
|
363
|
+
static ddog_Profile *serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state, ddog_Timespec start_timestamp_for_next_profile) {
|
|
361
364
|
int error;
|
|
362
365
|
int previously_active_slot = state->active_slot;
|
|
363
366
|
|
|
@@ -368,6 +371,10 @@ static ddprof_ffi_Profile *serializer_flip_active_and_inactive_slots(struct stac
|
|
|
368
371
|
pthread_mutex_t *previously_active = (previously_active_slot == 1) ? &state->slot_one_mutex : &state->slot_two_mutex;
|
|
369
372
|
pthread_mutex_t *previously_inactive = (previously_active_slot == 1) ? &state->slot_two_mutex : &state->slot_one_mutex;
|
|
370
373
|
|
|
374
|
+
// Before making this profile active, we reset it so that it uses the correct timestamp for its start
|
|
375
|
+
ddog_Profile *previously_inactive_profile = (previously_active_slot == 1) ? state->slot_two_profile : state->slot_one_profile;
|
|
376
|
+
if (!ddog_Profile_reset(previously_inactive_profile, &start_timestamp_for_next_profile)) rb_raise(rb_eRuntimeError, "Failed to reset profile");
|
|
377
|
+
|
|
371
378
|
// Release the lock, thus making this slot active
|
|
372
379
|
error = pthread_mutex_unlock(previously_inactive);
|
|
373
380
|
if (error) rb_syserr_fail(error, "Unexpected failure during serializer_flip_active_and_inactive_slots for previously_inactive");
|
|
@@ -420,3 +427,12 @@ static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
|
|
|
420
427
|
rb_syserr_fail(error, "Unexpected failure when checking mutex state");
|
|
421
428
|
}
|
|
422
429
|
}
|
|
430
|
+
|
|
431
|
+
// Note that this is using CLOCK_REALTIME (e.g. actual time since unix epoch) and not the CLOCK_MONOTONIC as we use in other parts of the codebase
|
|
432
|
+
static ddog_Timespec time_now() {
|
|
433
|
+
struct timespec current_time;
|
|
434
|
+
|
|
435
|
+
if (clock_gettime(CLOCK_REALTIME, ¤t_time) != 0) rb_sys_fail("Failed to read CLOCK_REALTIME");
|
|
436
|
+
|
|
437
|
+
return (ddog_Timespec) {.seconds = current_time.tv_sec, .nanoseconds = (uint32_t) current_time.tv_nsec};
|
|
438
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <
|
|
3
|
+
#include <datadog/profiling.h>
|
|
4
4
|
|
|
5
|
-
// Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `
|
|
5
|
+
// Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `DDOG_CHARSLICE_C`.
|
|
6
6
|
// `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.2 CI test images)
|
|
7
7
|
// tripped when compiling `enabled_value_types` using `-std=gnu99` due to the extra cast that is included in
|
|
8
|
-
// `
|
|
8
|
+
// `DDOG_CHARSLICE_C` with the following error:
|
|
9
9
|
//
|
|
10
10
|
// ```
|
|
11
11
|
// compiling ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c
|
|
12
12
|
// ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c:23:1: error: initializer element is not constant
|
|
13
|
-
// static const
|
|
13
|
+
// static const ddog_ValueType enabled_value_types[] = {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE};
|
|
14
14
|
// ^
|
|
15
15
|
// ```
|
|
16
16
|
#define VALUE_STRING(string) {.ptr = "" string, .len = sizeof(string) - 1}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
#define HEAP_LIVE_SIZE_VALUE {.type_ = VALUE_STRING("heap-live-size"), .unit = VALUE_STRING("bytes")}
|
|
24
24
|
#define HEAP_LIVE_SAMPLES_VALUE {.type_ = VALUE_STRING("heap-live-samples"), .unit = VALUE_STRING("count")}
|
|
25
25
|
|
|
26
|
-
static const
|
|
26
|
+
static const ddog_ValueType enabled_value_types[] = {
|
|
27
27
|
#define CPU_TIME_VALUE_POS 0
|
|
28
28
|
CPU_TIME_VALUE,
|
|
29
29
|
#define CPU_SAMPLES_VALUE_POS 1
|
|
@@ -32,7 +32,7 @@ static const ddprof_ffi_ValueType enabled_value_types[] = {
|
|
|
32
32
|
WALL_TIME_VALUE
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
#define ENABLED_VALUE_TYPES_COUNT (sizeof(enabled_value_types) / sizeof(
|
|
35
|
+
#define ENABLED_VALUE_TYPES_COUNT (sizeof(enabled_value_types) / sizeof(ddog_ValueType))
|
|
36
36
|
|
|
37
|
-
void record_sample(VALUE recorder_instance,
|
|
37
|
+
void record_sample(VALUE recorder_instance, ddog_Sample sample);
|
|
38
38
|
VALUE enforce_recorder_instance(VALUE object);
|
data/lib/datadog/appsec/event.rb
CHANGED
|
@@ -51,6 +51,7 @@ module Datadog
|
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
# rubocop:disable Metrics/MethodLength
|
|
54
55
|
def self.record_via_span(*events) # rubocop:disable Metrics/AbcSize
|
|
55
56
|
events.group_by { |e| e[:trace] }.each do |trace, event_group|
|
|
56
57
|
unless trace
|
|
@@ -59,6 +60,10 @@ module Datadog
|
|
|
59
60
|
end
|
|
60
61
|
|
|
61
62
|
trace.keep!
|
|
63
|
+
trace.set_tag(
|
|
64
|
+
Datadog::Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
|
65
|
+
Datadog::Tracing::Sampling::Ext::Decision::ASM
|
|
66
|
+
)
|
|
62
67
|
|
|
63
68
|
# prepare and gather tags to apply
|
|
64
69
|
trace_tags = event_group.each_with_object({}) do |event, tags|
|
|
@@ -106,6 +111,7 @@ module Datadog
|
|
|
106
111
|
end
|
|
107
112
|
end
|
|
108
113
|
end
|
|
114
|
+
# rubocop:enable Metrics/MethodLength
|
|
109
115
|
end
|
|
110
116
|
end
|
|
111
117
|
end
|
|
@@ -181,7 +181,7 @@ module Datadog
|
|
|
181
181
|
|
|
182
182
|
next unless response && !response.internal_error? && response.service_rates
|
|
183
183
|
|
|
184
|
-
sampler.update(response.service_rates)
|
|
184
|
+
sampler.update(response.service_rates, decision: Tracing::Sampling::Ext::Decision::AGENT_RATE)
|
|
185
185
|
end
|
|
186
186
|
end
|
|
187
187
|
|
|
@@ -251,7 +251,9 @@ module Datadog
|
|
|
251
251
|
recorder = Datadog::Profiling::StackRecorder.new
|
|
252
252
|
collector = Datadog::Profiling::Collectors::CpuAndWallTimeWorker.new(
|
|
253
253
|
recorder: recorder,
|
|
254
|
-
max_frames: settings.profiling.advanced.max_frames
|
|
254
|
+
max_frames: settings.profiling.advanced.max_frames,
|
|
255
|
+
tracer: tracer,
|
|
256
|
+
gc_profiling_enabled: should_enable_gc_profiling?(settings)
|
|
255
257
|
)
|
|
256
258
|
else
|
|
257
259
|
trace_identifiers_helper = Profiling::TraceIdentifiers::Helper.new(
|
|
@@ -320,18 +322,6 @@ module Datadog
|
|
|
320
322
|
|
|
321
323
|
def build_profiler_transport(settings, agent_settings)
|
|
322
324
|
settings.profiling.exporter.transport ||
|
|
323
|
-
if settings.profiling.advanced.legacy_transport_enabled
|
|
324
|
-
require_relative '../../profiling/transport/http'
|
|
325
|
-
|
|
326
|
-
Datadog.logger.warn('Using legacy profiling transport. Do not use unless instructed to by support.')
|
|
327
|
-
|
|
328
|
-
Profiling::Transport::HTTP.default(
|
|
329
|
-
agent_settings: agent_settings,
|
|
330
|
-
site: settings.site,
|
|
331
|
-
api_key: settings.api_key,
|
|
332
|
-
profiling_upload_timeout_seconds: settings.profiling.upload.timeout_seconds
|
|
333
|
-
)
|
|
334
|
-
end ||
|
|
335
325
|
Profiling::HttpTransport.new(
|
|
336
326
|
agent_settings: agent_settings,
|
|
337
327
|
site: settings.site,
|
|
@@ -339,6 +329,22 @@ module Datadog
|
|
|
339
329
|
upload_timeout_seconds: settings.profiling.upload.timeout_seconds,
|
|
340
330
|
)
|
|
341
331
|
end
|
|
332
|
+
|
|
333
|
+
def should_enable_gc_profiling?(settings)
|
|
334
|
+
return true if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3')
|
|
335
|
+
|
|
336
|
+
# See comments on the setting definition for more context on why it exists.
|
|
337
|
+
if settings.profiling.advanced.force_enable_gc_profiling
|
|
338
|
+
Datadog.logger.debug(
|
|
339
|
+
'Profiling time/resources spent in Garbage Collection force enabled. Do not use Ractors in combination ' \
|
|
340
|
+
'with this option as profiles will be incomplete.'
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
true
|
|
344
|
+
else
|
|
345
|
+
false
|
|
346
|
+
end
|
|
347
|
+
end
|
|
342
348
|
end
|
|
343
349
|
|
|
344
350
|
attr_reader \
|
|
@@ -234,11 +234,17 @@ module Datadog
|
|
|
234
234
|
# categorization of stack traces.
|
|
235
235
|
option :code_provenance_enabled, default: true
|
|
236
236
|
|
|
237
|
-
#
|
|
238
|
-
#
|
|
237
|
+
# No longer does anything, and will be removed on dd-trace-rb 2.0.
|
|
238
|
+
#
|
|
239
|
+
# This was added as a temporary support option in case of issues with the new `Profiling::HttpTransport` class
|
|
240
|
+
# but we're now confident it's working nicely so we've removed the old code path.
|
|
239
241
|
option :legacy_transport_enabled do |o|
|
|
240
|
-
o.
|
|
241
|
-
|
|
242
|
+
o.on_set do
|
|
243
|
+
Datadog.logger.warn(
|
|
244
|
+
'The profiling.advanced.legacy_transport_enabled setting has been deprecated for removal and no ' \
|
|
245
|
+
'longer does anything. Please remove it from your Datadog.configure block.'
|
|
246
|
+
)
|
|
247
|
+
end
|
|
242
248
|
end
|
|
243
249
|
|
|
244
250
|
# Forces enabling the new profiler. We do not yet recommend turning on this option.
|
|
@@ -250,6 +256,25 @@ module Datadog
|
|
|
250
256
|
o.default { env_to_bool('DD_PROFILING_FORCE_ENABLE_NEW', false) }
|
|
251
257
|
o.lazy
|
|
252
258
|
end
|
|
259
|
+
|
|
260
|
+
# Forces enabling of profiling of time/resources spent in Garbage Collection.
|
|
261
|
+
#
|
|
262
|
+
# Note that setting this to "false" (or not setting it) will not prevent the feature from being
|
|
263
|
+
# being automatically enabled in the future.
|
|
264
|
+
#
|
|
265
|
+
# This toggle was added because, although this feature is safe and enabled by default on Ruby 2.x,
|
|
266
|
+
# on Ruby 3.x it can break in applications that make use of Ractors due to two Ruby VM bugs:
|
|
267
|
+
# https://bugs.ruby-lang.org/issues/19112 AND https://bugs.ruby-lang.org/issues/18464.
|
|
268
|
+
#
|
|
269
|
+
# If you use Ruby 3.x and your application does not use Ractors (or if your Ruby has been patched), the
|
|
270
|
+
# feature is fully safe to enable and this toggle can be used to do so.
|
|
271
|
+
#
|
|
272
|
+
# We expect that once the above issue is patched, we'll automatically re-enable the feature on fixed Ruby
|
|
273
|
+
# versions.
|
|
274
|
+
option :force_enable_gc_profiling do |o|
|
|
275
|
+
o.default { env_to_bool('DD_PROFILING_FORCE_ENABLE_GC', false) }
|
|
276
|
+
o.lazy
|
|
277
|
+
end
|
|
253
278
|
end
|
|
254
279
|
|
|
255
280
|
# @public_api
|
|
@@ -700,6 +725,19 @@ module Datadog
|
|
|
700
725
|
o.lazy
|
|
701
726
|
end
|
|
702
727
|
end
|
|
728
|
+
|
|
729
|
+
# Maximum size for the `x-datadog-tags` distributed trace tags header.
|
|
730
|
+
#
|
|
731
|
+
# If the serialized size of distributed trace tags is larger than this value, it will
|
|
732
|
+
# not be parsed if incoming, nor exported if outgoing. An error message will be logged
|
|
733
|
+
# in this case.
|
|
734
|
+
#
|
|
735
|
+
# @default `DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH` environment variable, otherwise `512`
|
|
736
|
+
# @return [Integer]
|
|
737
|
+
option :x_datadog_tags_max_length do |o|
|
|
738
|
+
o.default { env_to_int(Tracing::Configuration::Ext::Distributed::ENV_X_DATADOG_TAGS_MAX_LENGTH, 512) }
|
|
739
|
+
o.lazy
|
|
740
|
+
end
|
|
703
741
|
end
|
|
704
742
|
|
|
705
743
|
# The `version` tag in Datadog. Use it to enable [Deployment Tracking](https://docs.datadoghq.com/tracing/deployment_tracking/).
|
|
@@ -106,10 +106,14 @@ module Datadog
|
|
|
106
106
|
Datadog.configuration.version
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
# @return [String] target agent URL for trace flushing
|
|
109
|
+
# @return [String, nil] target agent URL for trace flushing
|
|
110
110
|
def agent_url
|
|
111
111
|
# Retrieve the effect agent URL, regardless of how it was configured
|
|
112
112
|
transport = Tracing.send(:tracer).writer.transport
|
|
113
|
+
|
|
114
|
+
# return `nil` with IO transport
|
|
115
|
+
return unless transport.respond_to?(:client)
|
|
116
|
+
|
|
113
117
|
adapter = transport.client.api.adapter
|
|
114
118
|
adapter.url
|
|
115
119
|
end
|
|
@@ -6,10 +6,13 @@ require 'zlib'
|
|
|
6
6
|
module Datadog
|
|
7
7
|
module Core
|
|
8
8
|
module Utils
|
|
9
|
-
#
|
|
9
|
+
# Compression/decompression utility functions.
|
|
10
|
+
#
|
|
11
|
+
# @deprecated This is no longer used by ddtrace and will be removed in 2.0.
|
|
10
12
|
module Compression
|
|
11
13
|
module_function
|
|
12
14
|
|
|
15
|
+
# @deprecated This is no longer used by ddtrace and will be removed in 2.0.
|
|
13
16
|
def gzip(string, level: nil, strategy: nil)
|
|
14
17
|
sio = StringIO.new
|
|
15
18
|
sio.binmode
|
|
@@ -19,6 +22,7 @@ module Datadog
|
|
|
19
22
|
sio.string
|
|
20
23
|
end
|
|
21
24
|
|
|
25
|
+
# @deprecated This is no longer used by ddtrace and will be removed in 2.0.
|
|
22
26
|
def gunzip(string, encoding = ::Encoding::ASCII_8BIT)
|
|
23
27
|
sio = StringIO.new(string)
|
|
24
28
|
gz = Zlib::GzipReader.new(sio, encoding: encoding)
|
data/lib/datadog/core.rb
CHANGED
|
@@ -1,59 +1,5 @@
|
|
|
1
1
|
# typed: strict
|
|
2
2
|
|
|
3
|
-
# TODO: Move these requires to smaller modules.
|
|
4
|
-
# Would be better to lazy load these; not
|
|
5
|
-
# all of these components will be used in
|
|
6
|
-
# every application.
|
|
7
|
-
# require_relative 'core/buffer/cruby'
|
|
8
|
-
# require_relative 'core/buffer/random'
|
|
9
|
-
# require_relative 'core/buffer/thread_safe'
|
|
10
|
-
# require_relative 'core/chunker'
|
|
11
|
-
# require_relative 'core/configuration'
|
|
12
|
-
# require_relative 'core/diagnostics/environment_logger'
|
|
13
|
-
# require_relative 'core/diagnostics/ext'
|
|
14
|
-
# require_relative 'core/diagnostics/health'
|
|
15
|
-
# require_relative 'core/encoding'
|
|
16
|
-
# require_relative 'core/environment/cgroup'
|
|
17
|
-
# require_relative 'core/environment/class_count'
|
|
18
|
-
# require_relative 'core/environment/container'
|
|
19
|
-
# require_relative 'core/environment/ext'
|
|
20
|
-
# require_relative 'core/environment/gc'
|
|
21
|
-
# require_relative 'core/environment/identity'
|
|
22
|
-
# require_relative 'core/environment/socket'
|
|
23
|
-
# require_relative 'core/environment/thread_count'
|
|
24
|
-
# require_relative 'core/environment/variable_helpers'
|
|
25
|
-
# require_relative 'core/environment/vm_cache'
|
|
26
|
-
# require_relative 'core/error'
|
|
27
|
-
# require_relative 'core/event'
|
|
28
|
-
# require_relative 'core/git/ext'
|
|
29
|
-
# require_relative 'core/logger'
|
|
30
|
-
# require_relative 'core/metrics/client'
|
|
31
|
-
# require_relative 'core/metrics/ext'
|
|
32
|
-
# require_relative 'core/metrics/helpers'
|
|
33
|
-
# require_relative 'core/metrics/logging'
|
|
34
|
-
# require_relative 'core/metrics/metric'
|
|
35
|
-
# require_relative 'core/metrics/options'
|
|
36
|
-
# require_relative 'core/pin'
|
|
37
|
-
# require_relative 'core/quantization/hash'
|
|
38
|
-
# require_relative 'core/quantization/http'
|
|
39
|
-
# require_relative 'core/runtime/ext'
|
|
40
|
-
# require_relative 'core/runtime/metrics'
|
|
41
|
-
# require_relative 'core/utils'
|
|
42
|
-
# require_relative 'core/utils/compression'
|
|
43
|
-
# require_relative 'core/utils/database'
|
|
44
|
-
# require_relative 'core/utils/forking'
|
|
45
|
-
# require_relative 'core/utils/object_set'
|
|
46
|
-
# require_relative 'core/utils/only_once'
|
|
47
|
-
# require_relative 'core/utils/sequence'
|
|
48
|
-
# require_relative 'core/utils/string_table'
|
|
49
|
-
# require_relative 'core/utils/time'
|
|
50
|
-
# require_relative 'core/worker'
|
|
51
|
-
# require_relative 'core/workers/async'
|
|
52
|
-
# require_relative 'core/workers/interval_loop'
|
|
53
|
-
# require_relative 'core/workers/polling'
|
|
54
|
-
# require_relative 'core/workers/queue'
|
|
55
|
-
# require_relative 'core/workers/runtime_metrics'
|
|
56
|
-
|
|
57
3
|
require_relative 'core/extensions'
|
|
58
4
|
|
|
59
5
|
# We must load core extensions to make certain global APIs
|
|
@@ -11,8 +11,9 @@ module Datadog
|
|
|
11
11
|
#
|
|
12
12
|
# Methods prefixed with _native_ are implemented in `collectors_cpu_and_wall_time.c`
|
|
13
13
|
class CpuAndWallTime
|
|
14
|
-
def initialize(recorder:, max_frames:)
|
|
15
|
-
|
|
14
|
+
def initialize(recorder:, max_frames:, tracer:)
|
|
15
|
+
tracer_context_key = safely_extract_context_key_from(tracer)
|
|
16
|
+
self.class._native_initialize(self, recorder, max_frames, tracer_context_key)
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def inspect
|
|
@@ -21,6 +22,15 @@ module Datadog
|
|
|
21
22
|
result[-1] = "#{self.class._native_inspect(self)}>"
|
|
22
23
|
result
|
|
23
24
|
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def safely_extract_context_key_from(tracer)
|
|
29
|
+
tracer &&
|
|
30
|
+
tracer.respond_to?(:provider) &&
|
|
31
|
+
# NOTE: instance_variable_get always works, even on nil -- it just returns nil if the variable doesn't exist
|
|
32
|
+
tracer.provider.instance_variable_get(:@context).instance_variable_get(:@key)
|
|
33
|
+
end
|
|
24
34
|
end
|
|
25
35
|
end
|
|
26
36
|
end
|
|
@@ -18,9 +18,11 @@ module Datadog
|
|
|
18
18
|
def initialize(
|
|
19
19
|
recorder:,
|
|
20
20
|
max_frames:,
|
|
21
|
-
|
|
21
|
+
tracer:,
|
|
22
|
+
gc_profiling_enabled:,
|
|
23
|
+
cpu_and_wall_time_collector: CpuAndWallTime.new(recorder: recorder, max_frames: max_frames, tracer: tracer)
|
|
22
24
|
)
|
|
23
|
-
self.class._native_initialize(self, cpu_and_wall_time_collector)
|
|
25
|
+
self.class._native_initialize(self, cpu_and_wall_time_collector, gc_profiling_enabled)
|
|
24
26
|
@worker_thread = nil
|
|
25
27
|
@failure_exception = nil
|
|
26
28
|
@start_stop_mutex = Mutex.new
|
|
@@ -28,7 +30,7 @@ module Datadog
|
|
|
28
30
|
|
|
29
31
|
def start
|
|
30
32
|
@start_stop_mutex.synchronize do
|
|
31
|
-
return if @worker_thread
|
|
33
|
+
return if @worker_thread && @worker_thread.alive?
|
|
32
34
|
|
|
33
35
|
Datadog.logger.debug { "Starting thread for: #{self}" }
|
|
34
36
|
@worker_thread = Thread.new do
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# typed: true
|
|
2
2
|
|
|
3
3
|
require_relative 'ext'
|
|
4
|
-
require_relative '../core/utils/compression'
|
|
5
4
|
require_relative 'tag_builder'
|
|
6
5
|
|
|
7
6
|
module Datadog
|
|
@@ -60,10 +59,9 @@ module Datadog
|
|
|
60
59
|
start: start,
|
|
61
60
|
finish: finish,
|
|
62
61
|
pprof_file_name: Datadog::Profiling::Ext::Transport::HTTP::PPROF_DEFAULT_FILENAME,
|
|
63
|
-
pprof_data:
|
|
62
|
+
pprof_data: uncompressed_pprof.to_s,
|
|
64
63
|
code_provenance_file_name: Datadog::Profiling::Ext::Transport::HTTP::CODE_PROVENANCE_FILENAME,
|
|
65
|
-
code_provenance_data:
|
|
66
|
-
(Datadog::Core::Utils::Compression.gzip(uncompressed_code_provenance) if uncompressed_code_provenance),
|
|
64
|
+
code_provenance_data: uncompressed_code_provenance,
|
|
67
65
|
tags_as_array: Datadog::Profiling::TagBuilder.call(settings: Datadog.configuration).to_a,
|
|
68
66
|
)
|
|
69
67
|
end
|
|
@@ -58,7 +58,7 @@ module Datadog
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
# Used to log soft failures in `
|
|
61
|
+
# Used to log soft failures in `ddog_Vec_tag_push` (e.g. we still report the profile in these cases)
|
|
62
62
|
# Called from native code
|
|
63
63
|
def self.log_failure_to_process_tag(failure_details)
|
|
64
64
|
Datadog.logger.warn("Failed to add tag to profiling request: #{failure_details}")
|
|
@@ -21,6 +21,7 @@ module Datadog
|
|
|
21
21
|
PROPAGATION_STYLE_B3_SINGLE_HEADER = 'B3 single header'.freeze
|
|
22
22
|
ENV_PROPAGATION_STYLE_INJECT = 'DD_PROPAGATION_STYLE_INJECT'.freeze
|
|
23
23
|
ENV_PROPAGATION_STYLE_EXTRACT = 'DD_PROPAGATION_STYLE_EXTRACT'.freeze
|
|
24
|
+
ENV_X_DATADOG_TAGS_MAX_LENGTH = 'DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH'.freeze
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
# @public_api
|
|
@@ -33,6 +33,8 @@ module Datadog
|
|
|
33
33
|
span.name = Ext::SPAN_COMMAND
|
|
34
34
|
span.resource = context.safely(:resource)
|
|
35
35
|
|
|
36
|
+
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
|
|
37
|
+
|
|
36
38
|
span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
|
|
37
39
|
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_COMMAND)
|
|
38
40
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative '../../metadata/ext'
|
|
4
4
|
require_relative '../analytics'
|
|
5
5
|
require_relative 'ext'
|
|
6
|
+
require_relative '../ext'
|
|
6
7
|
require_relative 'quantize'
|
|
7
8
|
|
|
8
9
|
module Datadog
|
|
@@ -37,6 +38,9 @@ module Datadog
|
|
|
37
38
|
|
|
38
39
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, hostname)
|
|
39
40
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, port)
|
|
41
|
+
|
|
42
|
+
span.set_tag(Contrib::Ext::DB::TAG_SYSTEM, Ext::TAG_SYSTEM)
|
|
43
|
+
|
|
40
44
|
cmd = Quantize.format_command(op, args)
|
|
41
45
|
span.set_tag(Ext::TAG_COMMAND, cmd)
|
|
42
46
|
|