datadog 2.40.0 → 2.41.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 +85 -58
- data/ext/datadog_profiling_native_extension/collectors_stack.c +2 -2
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +26 -12
- data/ext/libdatadog_api/trace_exporter.c +409 -71
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/api_client.rb +1 -1
- data/lib/datadog/ai_guard/evaluation/request.rb +8 -8
- data/lib/datadog/ai_guard/evaluation.rb +10 -3
- data/lib/datadog/ai_guard/ext.rb +1 -1
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +21 -42
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +1 -1
- data/lib/datadog/appsec/configuration.rb +2 -2
- data/lib/datadog/appsec/context.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +1 -1
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +2 -2
- data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +2 -2
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +2 -2
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/ext.rb +2 -2
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +12 -12
- data/lib/datadog/appsec/response.rb +1 -1
- data/lib/datadog/appsec/route_normalizer/route_pattern.rb +3 -3
- data/lib/datadog/appsec/security_engine/engine.rb +3 -3
- data/lib/datadog/core/configuration/components.rb +2 -2
- data/lib/datadog/core/configuration/option_definition.rb +1 -1
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +36 -1
- data/lib/datadog/core/metrics/helpers.rb +1 -1
- data/lib/datadog/core/metrics/options.rb +2 -2
- data/lib/datadog/core/process_discovery.rb +1 -1
- data/lib/datadog/core/remote/client.rb +1 -1
- data/lib/datadog/core/remote/configuration/repository.rb +2 -2
- data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -1
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +1 -1
- data/lib/datadog/core/telemetry/event/app_started.rb +5 -24
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +1 -1
- data/lib/datadog/core/telemetry/event/log.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +2 -2
- data/lib/datadog/core/telemetry/request.rb +2 -2
- data/lib/datadog/core/transport/http.rb +1 -1
- data/lib/datadog/core/transport/transport.rb +1 -1
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +127 -43
- data/lib/datadog/data_streams/processor.rb +14 -14
- data/lib/datadog/di/el/compiler.rb +23 -0
- data/lib/datadog/di/el/expression.rb +8 -5
- data/lib/datadog/di/instrumenter.rb +5 -4
- data/lib/datadog/di/probe_builder.rb +5 -4
- data/lib/datadog/di/probe_notification_builder.rb +2 -2
- data/lib/datadog/di/serializer.rb +29 -4
- data/lib/datadog/error_tracking/component.rb +1 -1
- data/lib/datadog/kit/appsec/events/v2.rb +2 -2
- data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
- data/lib/datadog/open_feature/exposures/event.rb +5 -5
- data/lib/datadog/profiling/collectors/info.rb +1 -1
- data/lib/datadog/profiling/tasks/exec.rb +1 -1
- data/lib/datadog/symbol_database/extractor.rb +6 -6
- data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +5 -3
- data/lib/datadog/tracing/contrib/action_cable/events.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/events.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/action_view/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/services.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/ext.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/patchable.rb +1 -1
- data/lib/datadog/tracing/contrib/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/quantize.rb +36 -2
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +9 -3
- data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/utils/quantization/hash_formatter.rb +1 -1
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +1 -1
- data/lib/datadog/tracing/correlation.rb +2 -2
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +2 -2
- data/lib/datadog/tracing/distributed/baggage.rb +1 -2
- data/lib/datadog/tracing/metadata/tagging.rb +1 -1
- data/lib/datadog/tracing/remote.rb +2 -2
- data/lib/datadog/tracing/span.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/transport/io/traces.rb +1 -1
- data/lib/datadog/tracing/transport/native.rb +78 -54
- data/lib/datadog/tracing/writer.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +6 -5
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
|
+
#ifdef __GNUC__
|
|
3
|
+
#pragma GCC diagnostic push
|
|
4
|
+
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
5
|
+
#endif
|
|
6
|
+
#include <ruby/encoding.h>
|
|
7
|
+
#ifdef __GNUC__
|
|
8
|
+
#pragma GCC diagnostic pop
|
|
9
|
+
#endif
|
|
2
10
|
#include <ruby/thread.h>
|
|
11
|
+
#include <limits.h>
|
|
3
12
|
#include <stdbool.h>
|
|
13
|
+
#include <string.h>
|
|
4
14
|
#include <datadog/data-pipeline.h>
|
|
5
15
|
#include <datadog/shared-runtime.h>
|
|
6
16
|
|
|
@@ -12,8 +22,12 @@
|
|
|
12
22
|
* Forward declarations
|
|
13
23
|
* ======================================================================== */
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
|
|
25
|
+
typedef struct {
|
|
26
|
+
ddog_TracerSpan *span;
|
|
27
|
+
} raw_span_owner;
|
|
28
|
+
|
|
29
|
+
/* Internal: convert a Ruby Span into the supplied raw Rust span owner */
|
|
30
|
+
static void convert_ruby_span_to_rust(VALUE span, raw_span_owner *owner);
|
|
17
31
|
|
|
18
32
|
/* TracerSpan methods */
|
|
19
33
|
static VALUE _native_from_span(VALUE klass, VALUE span);
|
|
@@ -51,9 +65,15 @@ static ID at_duration_id;
|
|
|
51
65
|
static ID at_status_id;
|
|
52
66
|
static ID at_meta_id;
|
|
53
67
|
static ID at_metrics_id;
|
|
68
|
+
static ID at_metastruct_id;
|
|
54
69
|
|
|
55
70
|
/* Method IDs for time / integer operations */
|
|
56
71
|
static ID id_duration_method;
|
|
72
|
+
static ID id_to_h;
|
|
73
|
+
static ID id_negative_p;
|
|
74
|
+
|
|
75
|
+
/* Resolved lazily because AppSec may load after this extension. */
|
|
76
|
+
static VALUE serializable_backtrace_class = Qnil;
|
|
57
77
|
|
|
58
78
|
/* Response class (loaded from Ruby) */
|
|
59
79
|
static VALUE response_class = Qnil;
|
|
@@ -101,7 +121,7 @@ static void tracer_span_dfree(void *ptr) {
|
|
|
101
121
|
*/
|
|
102
122
|
typedef struct {
|
|
103
123
|
ddog_TraceExporter *exporter;
|
|
104
|
-
const
|
|
124
|
+
const ddog_ForkSafeRuntime *runtime;
|
|
105
125
|
} trace_exporter_t;
|
|
106
126
|
|
|
107
127
|
static const rb_data_type_t trace_exporter_typed_data = {
|
|
@@ -305,31 +325,320 @@ static int metrics_iter_cb(VALUE key, VALUE value, VALUE arg) {
|
|
|
305
325
|
return ST_CONTINUE;
|
|
306
326
|
}
|
|
307
327
|
|
|
308
|
-
|
|
309
|
-
*
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
*
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
328
|
+
typedef struct {
|
|
329
|
+
ddog_TracerValueToken *tokens;
|
|
330
|
+
size_t len;
|
|
331
|
+
size_t capacity;
|
|
332
|
+
st_table *active;
|
|
333
|
+
uint8_t **scratch;
|
|
334
|
+
size_t scratch_len;
|
|
335
|
+
size_t scratch_capacity;
|
|
336
|
+
} structured_value_ctx;
|
|
337
|
+
|
|
338
|
+
static ddog_TracerValueToken *append_structured_value_token(
|
|
339
|
+
structured_value_ctx *ctx, uint8_t kind) {
|
|
340
|
+
if (ctx->len == ctx->capacity) {
|
|
341
|
+
size_t capacity = ctx->capacity == 0 ? 16 : ctx->capacity * 2;
|
|
342
|
+
if (capacity < ctx->capacity || capacity > SIZE_MAX / sizeof(*ctx->tokens)) {
|
|
343
|
+
rb_raise(rb_eNoMemError, "meta_struct token buffer is too large");
|
|
344
|
+
}
|
|
345
|
+
REALLOC_N(ctx->tokens, ddog_TracerValueToken, capacity);
|
|
346
|
+
ctx->capacity = capacity;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
ddog_TracerValueToken *token = &ctx->tokens[ctx->len++];
|
|
350
|
+
*token = (ddog_TracerValueToken){0};
|
|
351
|
+
token->kind = kind;
|
|
352
|
+
return token;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
static const uint8_t *copy_structured_value_bytes(
|
|
356
|
+
structured_value_ctx *ctx, VALUE string, size_t len) {
|
|
357
|
+
if (len == 0) return (const uint8_t *)"";
|
|
358
|
+
|
|
359
|
+
if (ctx->scratch_len == ctx->scratch_capacity) {
|
|
360
|
+
size_t capacity = ctx->scratch_capacity == 0 ? 8 : ctx->scratch_capacity * 2;
|
|
361
|
+
if (capacity < ctx->scratch_capacity || capacity > SIZE_MAX / sizeof(*ctx->scratch)) {
|
|
362
|
+
rb_raise(rb_eNoMemError, "meta_struct scratch buffer is too large");
|
|
363
|
+
}
|
|
364
|
+
REALLOC_N(ctx->scratch, uint8_t *, capacity);
|
|
365
|
+
ctx->scratch_capacity = capacity;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
uint8_t *copy = ruby_xmalloc(len);
|
|
369
|
+
ctx->scratch[ctx->scratch_len++] = copy;
|
|
370
|
+
/* ruby_xmalloc may trigger GC, so retrieve the Ruby buffer only after it
|
|
371
|
+
* returns and do not call Ruby again before the copy completes. */
|
|
372
|
+
memcpy(copy, RSTRING_PTR(string), len);
|
|
373
|
+
return copy;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
static void free_structured_value_ctx(structured_value_ctx *ctx) {
|
|
377
|
+
if (ctx->active != NULL) st_free_table(ctx->active);
|
|
378
|
+
for (size_t i = 0; i < ctx->scratch_len; i++) {
|
|
379
|
+
ruby_xfree(ctx->scratch[i]);
|
|
380
|
+
}
|
|
381
|
+
ruby_xfree(ctx->scratch);
|
|
382
|
+
ruby_xfree(ctx->tokens);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
static VALUE resolve_serializable_backtrace_class(void) {
|
|
386
|
+
if (serializable_backtrace_class != Qnil) return serializable_backtrace_class;
|
|
387
|
+
|
|
388
|
+
ID datadog_id = rb_intern("Datadog");
|
|
389
|
+
ID appsec_id = rb_intern("AppSec");
|
|
390
|
+
ID actions_handler_id = rb_intern("ActionsHandler");
|
|
391
|
+
ID backtrace_id = rb_intern("SerializableBacktrace");
|
|
392
|
+
if (!rb_const_defined(rb_cObject, datadog_id)) return Qnil;
|
|
393
|
+
VALUE datadog = rb_const_get(rb_cObject, datadog_id);
|
|
394
|
+
if (!rb_const_defined(datadog, appsec_id)) return Qnil;
|
|
395
|
+
VALUE appsec = rb_const_get(datadog, appsec_id);
|
|
396
|
+
if (!rb_const_defined(appsec, actions_handler_id)) return Qnil;
|
|
397
|
+
VALUE actions_handler = rb_const_get(appsec, actions_handler_id);
|
|
398
|
+
if (!rb_const_defined(actions_handler, backtrace_id)) return Qnil;
|
|
399
|
+
|
|
400
|
+
serializable_backtrace_class = rb_const_get(actions_handler, backtrace_id);
|
|
401
|
+
rb_global_variable(&serializable_backtrace_class);
|
|
402
|
+
return serializable_backtrace_class;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
static void append_structured_value(VALUE value, unsigned int depth,
|
|
406
|
+
structured_value_ctx *ctx);
|
|
407
|
+
|
|
408
|
+
typedef struct {
|
|
409
|
+
structured_value_ctx *ctx;
|
|
410
|
+
unsigned int depth;
|
|
411
|
+
} structured_hash_ctx;
|
|
412
|
+
|
|
413
|
+
static int append_structured_hash_entry(VALUE key, VALUE value, VALUE arg) {
|
|
414
|
+
structured_hash_ctx *hash_ctx = (structured_hash_ctx *)arg;
|
|
415
|
+
append_structured_value(key, hash_ctx->depth, hash_ctx->ctx);
|
|
416
|
+
append_structured_value(value, hash_ctx->depth, hash_ctx->ctx);
|
|
417
|
+
return ST_CONTINUE;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
static VALUE utf8_string(VALUE value) {
|
|
421
|
+
VALUE string = RB_TYPE_P(value, T_SYMBOL) ? rb_sym2str(value) : value;
|
|
422
|
+
string = rb_str_export_to_enc(string, rb_utf8_encoding());
|
|
423
|
+
if (rb_enc_str_coderange(string) == ENC_CODERANGE_BROKEN) {
|
|
424
|
+
rb_raise(rb_eEncodingError, "meta_struct string is not valid UTF-8");
|
|
425
|
+
}
|
|
426
|
+
return string;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
static void append_structured_value(VALUE value, unsigned int depth,
|
|
430
|
+
structured_value_ctx *ctx) {
|
|
431
|
+
if (value == Qnil) {
|
|
432
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_NIL);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
if (value == Qtrue || value == Qfalse) {
|
|
436
|
+
ddog_TracerValueToken *token =
|
|
437
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_BOOL);
|
|
438
|
+
token->bool_value = value == Qtrue ? 1 : 0;
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
if (RB_TYPE_P(value, T_FIXNUM) || RB_TYPE_P(value, T_BIGNUM)) {
|
|
442
|
+
if (RTEST(rb_funcall(value, id_negative_p, 0))) {
|
|
443
|
+
ddog_TracerValueToken *token =
|
|
444
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_I64);
|
|
445
|
+
token->i64_value = NUM2LL(value);
|
|
446
|
+
} else {
|
|
447
|
+
ddog_TracerValueToken *token =
|
|
448
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_U64);
|
|
449
|
+
token->u64_value = NUM2ULL(value);
|
|
450
|
+
}
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (RB_TYPE_P(value, T_FLOAT)) {
|
|
454
|
+
ddog_TracerValueToken *token =
|
|
455
|
+
append_structured_value_token(ctx, DDOG_TRACER_VALUE_F64);
|
|
456
|
+
token->f64_value = RFLOAT_VALUE(value);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
if (RB_TYPE_P(value, T_STRING) || RB_TYPE_P(value, T_SYMBOL)) {
|
|
460
|
+
bool binary = RB_TYPE_P(value, T_STRING) &&
|
|
461
|
+
rb_enc_get_index(value) == rb_ascii8bit_encindex();
|
|
462
|
+
VALUE string = binary ? value : utf8_string(value);
|
|
463
|
+
size_t len = (size_t)RSTRING_LEN(string);
|
|
464
|
+
ddog_TracerValueToken *token = append_structured_value_token(
|
|
465
|
+
ctx, binary ? DDOG_TRACER_VALUE_BINARY : DDOG_TRACER_VALUE_STRING);
|
|
466
|
+
token->bytes = (ddog_ByteSlice){
|
|
467
|
+
.ptr = copy_structured_value_bytes(ctx, string, len),
|
|
468
|
+
.len = len,
|
|
469
|
+
};
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
VALUE backtrace_class = resolve_serializable_backtrace_class();
|
|
474
|
+
if (backtrace_class != Qnil && rb_obj_is_kind_of(value, backtrace_class)) {
|
|
475
|
+
append_structured_value(rb_funcall(value, id_to_h, 0), depth, ctx);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (!RB_TYPE_P(value, T_ARRAY) && !RB_TYPE_P(value, T_HASH)) {
|
|
480
|
+
rb_raise(rb_eTypeError, "unsupported meta_struct value type: %s",
|
|
481
|
+
rb_obj_classname(value));
|
|
482
|
+
}
|
|
483
|
+
if (depth >= 64) {
|
|
484
|
+
rb_raise(rb_eArgError, "meta_struct value exceeds maximum depth of 64");
|
|
485
|
+
}
|
|
486
|
+
if (st_lookup(ctx->active, (st_data_t)value, NULL)) {
|
|
487
|
+
rb_raise(rb_eArgError, "meta_struct value contains a cycle");
|
|
488
|
+
}
|
|
489
|
+
st_insert(ctx->active, (st_data_t)value, 1);
|
|
490
|
+
|
|
491
|
+
size_t length = RB_TYPE_P(value, T_ARRAY) ? (size_t)RARRAY_LEN(value) : RHASH_SIZE(value);
|
|
492
|
+
if (length > UINT32_MAX) {
|
|
493
|
+
rb_raise(rb_eArgError, "meta_struct container exceeds u32::MAX entries");
|
|
494
|
+
}
|
|
495
|
+
ddog_TracerValueToken *token = append_structured_value_token(
|
|
496
|
+
ctx, RB_TYPE_P(value, T_ARRAY) ? DDOG_TRACER_VALUE_ARRAY : DDOG_TRACER_VALUE_MAP);
|
|
497
|
+
token->child_count = (uint32_t)length;
|
|
498
|
+
|
|
499
|
+
if (RB_TYPE_P(value, T_ARRAY)) {
|
|
500
|
+
for (size_t i = 0; i < length; i++) {
|
|
501
|
+
append_structured_value(rb_ary_entry(value, (long)i), depth + 1, ctx);
|
|
502
|
+
}
|
|
503
|
+
} else {
|
|
504
|
+
structured_hash_ctx hash_ctx = {.ctx = ctx, .depth = depth + 1};
|
|
505
|
+
rb_hash_foreach(value, append_structured_hash_entry, (VALUE)&hash_ctx);
|
|
506
|
+
}
|
|
507
|
+
st_delete(ctx->active, (st_data_t *)&value, NULL);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
typedef struct {
|
|
511
|
+
const uint8_t *key;
|
|
512
|
+
size_t key_len;
|
|
513
|
+
structured_value_ctx value;
|
|
514
|
+
} prepared_metastruct_entry;
|
|
515
|
+
|
|
516
|
+
typedef struct {
|
|
517
|
+
prepared_metastruct_entry *entries;
|
|
518
|
+
size_t len;
|
|
519
|
+
size_t capacity;
|
|
520
|
+
} prepared_metastruct;
|
|
521
|
+
|
|
522
|
+
static void free_prepared_metastruct(prepared_metastruct *prepared) {
|
|
523
|
+
for (size_t i = 0; i < prepared->len; i++) {
|
|
524
|
+
free_structured_value_ctx(&prepared->entries[i].value);
|
|
525
|
+
}
|
|
526
|
+
ruby_xfree(prepared->entries);
|
|
527
|
+
*prepared = (prepared_metastruct){0};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
static prepared_metastruct_entry *append_prepared_metastruct_entry(
|
|
531
|
+
prepared_metastruct *prepared) {
|
|
532
|
+
if (prepared->len == prepared->capacity) {
|
|
533
|
+
size_t capacity = prepared->capacity == 0 ? 4 : prepared->capacity * 2;
|
|
534
|
+
if (capacity < prepared->capacity || capacity > SIZE_MAX / sizeof(*prepared->entries)) {
|
|
535
|
+
rb_raise(rb_eNoMemError, "meta_struct entry buffer is too large");
|
|
536
|
+
}
|
|
537
|
+
REALLOC_N(prepared->entries, prepared_metastruct_entry, capacity);
|
|
538
|
+
prepared->capacity = capacity;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
prepared_metastruct_entry *entry = &prepared->entries[prepared->len++];
|
|
542
|
+
*entry = (prepared_metastruct_entry){0};
|
|
543
|
+
entry->value.active = st_init_numtable();
|
|
544
|
+
return entry;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
typedef struct {
|
|
548
|
+
prepared_metastruct *prepared;
|
|
549
|
+
long skipped;
|
|
550
|
+
} metastruct_prepare_ctx;
|
|
551
|
+
|
|
552
|
+
static int prepare_metastruct_iter_cb(VALUE key, VALUE value, VALUE arg) {
|
|
553
|
+
metastruct_prepare_ctx *ctx = (metastruct_prepare_ctx *)arg;
|
|
554
|
+
|
|
555
|
+
/* The agent meta_struct contract requires string keys. Accept symbols as a
|
|
556
|
+
* Ruby convenience, but do not encode other key types differently from the
|
|
557
|
+
* native tracer implementations. */
|
|
558
|
+
if (RB_TYPE_P(key, T_SYMBOL)) {
|
|
559
|
+
key = rb_sym2str(key);
|
|
560
|
+
} else if (!RB_TYPE_P(key, T_STRING)) {
|
|
561
|
+
ctx->skipped++;
|
|
562
|
+
return ST_CONTINUE;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
key = utf8_string(key);
|
|
566
|
+
prepared_metastruct_entry *entry =
|
|
567
|
+
append_prepared_metastruct_entry(ctx->prepared);
|
|
568
|
+
entry->key_len = (size_t)RSTRING_LEN(key);
|
|
569
|
+
entry->key = copy_structured_value_bytes(
|
|
570
|
+
&entry->value, key, entry->key_len);
|
|
571
|
+
append_structured_value(value, 0, &entry->value);
|
|
572
|
+
|
|
573
|
+
return ST_CONTINUE;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
typedef struct {
|
|
577
|
+
VALUE span;
|
|
578
|
+
prepared_metastruct *prepared;
|
|
579
|
+
} prepare_metastruct_call;
|
|
580
|
+
|
|
581
|
+
static VALUE prepare_metastruct_body(VALUE arg) {
|
|
582
|
+
prepare_metastruct_call *call = (prepare_metastruct_call *)arg;
|
|
583
|
+
VALUE metastruct = rb_ivar_get(call->span, at_metastruct_id);
|
|
584
|
+
if (metastruct == Qnil) return Qnil;
|
|
585
|
+
|
|
586
|
+
VALUE values = rb_funcall(metastruct, id_to_h, 0);
|
|
587
|
+
Check_Type(values, T_HASH);
|
|
588
|
+
if (RHASH_SIZE(values) == 0) return Qnil;
|
|
589
|
+
|
|
590
|
+
metastruct_prepare_ctx ctx = {.prepared = call->prepared, .skipped = 0};
|
|
591
|
+
rb_hash_foreach(values, prepare_metastruct_iter_cb, (VALUE)&ctx);
|
|
592
|
+
if (ctx.skipped > 0) {
|
|
593
|
+
log_warning(rb_sprintf(
|
|
594
|
+
"Native trace exporter: skipped %ld meta_struct entries with non-string keys",
|
|
595
|
+
ctx.skipped));
|
|
596
|
+
}
|
|
597
|
+
return Qnil;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/* Prepare stable token storage before allocating the Rust span. Any Ruby
|
|
601
|
+
* callback or non-local exit is contained here, where deterministic cleanup
|
|
602
|
+
* does not need to account for Rust span ownership. */
|
|
603
|
+
static void prepare_metastruct(VALUE span, prepared_metastruct *prepared) {
|
|
604
|
+
prepare_metastruct_call call = {.span = span, .prepared = prepared};
|
|
317
605
|
int state = 0;
|
|
318
|
-
rb_protect(
|
|
606
|
+
rb_protect(prepare_metastruct_body, (VALUE)&call, &state);
|
|
319
607
|
if (state) {
|
|
320
|
-
|
|
608
|
+
free_prepared_metastruct(prepared);
|
|
321
609
|
rb_jump_tag(state);
|
|
322
610
|
}
|
|
323
611
|
}
|
|
324
612
|
|
|
613
|
+
static void set_prepared_metastruct(
|
|
614
|
+
ddog_TracerSpan *span, prepared_metastruct *prepared) {
|
|
615
|
+
for (size_t i = 0; i < prepared->len; i++) {
|
|
616
|
+
prepared_metastruct_entry *entry = &prepared->entries[i];
|
|
617
|
+
ddog_Slice_TracerValueToken tokens = {
|
|
618
|
+
.ptr = entry->value.tokens,
|
|
619
|
+
.len = entry->value.len,
|
|
620
|
+
};
|
|
621
|
+
ddog_CharSlice key = {
|
|
622
|
+
.ptr = (const char *)entry->key,
|
|
623
|
+
.len = entry->key_len,
|
|
624
|
+
};
|
|
625
|
+
ddog_TraceExporterError *err =
|
|
626
|
+
ddog_tracer_span_set_meta_struct(span, key, tokens);
|
|
627
|
+
if (err != NULL) {
|
|
628
|
+
free_prepared_metastruct(prepared);
|
|
629
|
+
check_exporter_error("Failed to set span meta_struct", err);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
free_prepared_metastruct(prepared);
|
|
633
|
+
}
|
|
325
634
|
/* ========================================================================
|
|
326
|
-
* Internal: convert a Ruby Span
|
|
635
|
+
* Internal: convert a Ruby Span into a raw_span_owner
|
|
327
636
|
*
|
|
328
|
-
* The
|
|
329
|
-
*
|
|
637
|
+
* The caller keeps its ensure handler active until the span is either wrapped
|
|
638
|
+
* in TypedData or consumed by a trace chunk.
|
|
330
639
|
* ======================================================================== */
|
|
331
640
|
|
|
332
|
-
static
|
|
641
|
+
static void convert_ruby_span_to_rust(VALUE span, raw_span_owner *owner) {
|
|
333
642
|
/* 1. Read Ruby ivars */
|
|
334
643
|
VALUE rb_name = rb_ivar_get(span, at_name_id);
|
|
335
644
|
VALUE rb_service = rb_ivar_get(span, at_service_id);
|
|
@@ -340,12 +649,12 @@ static ddog_TracerSpan *convert_ruby_span_to_rust(VALUE span) {
|
|
|
340
649
|
VALUE rb_trace_id = rb_ivar_get(span, at_trace_id_id);
|
|
341
650
|
VALUE rb_status = rb_ivar_get(span, at_status_id);
|
|
342
651
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
ddog_CharSlice type_s = nullable_char_slice(rb_type);
|
|
652
|
+
ENFORCE_TYPE(rb_name, T_STRING);
|
|
653
|
+
if (rb_service != Qnil) ENFORCE_TYPE(rb_service, T_STRING);
|
|
654
|
+
if (rb_resource != Qnil) ENFORCE_TYPE(rb_resource, T_STRING);
|
|
655
|
+
if (rb_type != Qnil) ENFORCE_TYPE(rb_type, T_STRING);
|
|
348
656
|
|
|
657
|
+
/* 2. Convert scalars that may call Ruby. */
|
|
349
658
|
uint64_t span_id = NUM2ULL(rb_span_id);
|
|
350
659
|
uint64_t parent_id = NUM2ULL(rb_parent_id);
|
|
351
660
|
int32_t error_val = NUM2INT(rb_status);
|
|
@@ -369,7 +678,18 @@ static ddog_TracerSpan *convert_ruby_span_to_rust(VALUE span) {
|
|
|
369
678
|
if (dur != Qnil) duration_ns = (int64_t)(NUM2DBL(dur) * 1e9);
|
|
370
679
|
}
|
|
371
680
|
|
|
372
|
-
/*
|
|
681
|
+
/* Structured-value normalisation can call Ruby code. Snapshot it before
|
|
682
|
+
* borrowing scalar string pointers or allocating the Rust span. */
|
|
683
|
+
prepared_metastruct metastruct = {0};
|
|
684
|
+
prepare_metastruct(span, &metastruct);
|
|
685
|
+
|
|
686
|
+
/* No Ruby calls may occur between borrowing these pointers and span_new. */
|
|
687
|
+
ddog_CharSlice name_s = char_slice_from_ruby_string(rb_name);
|
|
688
|
+
ddog_CharSlice service_s = nullable_char_slice(rb_service);
|
|
689
|
+
ddog_CharSlice resource_s = nullable_char_slice(rb_resource);
|
|
690
|
+
ddog_CharSlice type_s = nullable_char_slice(rb_type);
|
|
691
|
+
|
|
692
|
+
/* 3. Create Rust span and immediately consume the stable prepared values. */
|
|
373
693
|
ddog_TracerSpanFields fields = {
|
|
374
694
|
.service = service_s,
|
|
375
695
|
.name = name_s,
|
|
@@ -384,22 +704,20 @@ static ddog_TracerSpan *convert_ruby_span_to_rust(VALUE span) {
|
|
|
384
704
|
.error = error_val,
|
|
385
705
|
};
|
|
386
706
|
|
|
387
|
-
|
|
388
|
-
|
|
707
|
+
ddog_TraceExporterError *err = ddog_tracer_span_new(&owner->span, &fields);
|
|
708
|
+
if (err != NULL) free_prepared_metastruct(&metastruct);
|
|
389
709
|
check_exporter_error("Failed to create TracerSpan", err);
|
|
710
|
+
set_prepared_metastruct(owner->span, &metastruct);
|
|
390
711
|
|
|
391
712
|
/* 4. Populate meta and metrics */
|
|
392
|
-
hash_iter_ctx ctx = {.span =
|
|
713
|
+
hash_iter_ctx ctx = {.span = owner->span, .error = NULL, .skipped = 0};
|
|
393
714
|
|
|
394
715
|
VALUE rb_meta = rb_ivar_get(span, at_meta_id);
|
|
395
716
|
if (RB_TYPE_P(rb_meta, T_HASH) && RHASH_SIZE(rb_meta) > 0) {
|
|
396
717
|
rb_hash_foreach(rb_meta, meta_iter_cb, (VALUE)&ctx);
|
|
397
|
-
|
|
398
|
-
ddog_tracer_span_free(rust_span);
|
|
399
|
-
check_exporter_error("Failed to set span meta", ctx.error);
|
|
400
|
-
}
|
|
718
|
+
check_exporter_error("Failed to set span meta", ctx.error);
|
|
401
719
|
if (ctx.skipped > 0) {
|
|
402
|
-
|
|
720
|
+
log_warning(rb_sprintf(
|
|
403
721
|
"Native trace exporter: skipped %ld non-string meta entries",
|
|
404
722
|
ctx.skipped));
|
|
405
723
|
ctx.skipped = 0;
|
|
@@ -409,28 +727,49 @@ static ddog_TracerSpan *convert_ruby_span_to_rust(VALUE span) {
|
|
|
409
727
|
VALUE rb_metrics = rb_ivar_get(span, at_metrics_id);
|
|
410
728
|
if (RB_TYPE_P(rb_metrics, T_HASH) && RHASH_SIZE(rb_metrics) > 0) {
|
|
411
729
|
rb_hash_foreach(rb_metrics, metrics_iter_cb, (VALUE)&ctx);
|
|
412
|
-
|
|
413
|
-
ddog_tracer_span_free(rust_span);
|
|
414
|
-
check_exporter_error("Failed to set span metric", ctx.error);
|
|
415
|
-
}
|
|
730
|
+
check_exporter_error("Failed to set span metric", ctx.error);
|
|
416
731
|
if (ctx.skipped > 0) {
|
|
417
|
-
|
|
732
|
+
log_warning(rb_sprintf(
|
|
418
733
|
"Native trace exporter: skipped %ld non-numeric metrics entries",
|
|
419
734
|
ctx.skipped));
|
|
420
735
|
}
|
|
421
736
|
}
|
|
422
737
|
|
|
423
|
-
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
static VALUE free_raw_span(VALUE arg) {
|
|
741
|
+
raw_span_owner *owner = (raw_span_owner *)arg;
|
|
742
|
+
if (owner->span != NULL) {
|
|
743
|
+
ddog_tracer_span_free(owner->span);
|
|
744
|
+
owner->span = NULL;
|
|
745
|
+
}
|
|
746
|
+
return Qnil;
|
|
424
747
|
}
|
|
425
748
|
|
|
426
749
|
/* ========================================================================
|
|
427
750
|
* TracerSpan._native_from_span
|
|
428
751
|
* ======================================================================== */
|
|
429
752
|
|
|
753
|
+
typedef struct {
|
|
754
|
+
VALUE span;
|
|
755
|
+
raw_span_owner owner;
|
|
756
|
+
} wrap_span_ctx;
|
|
757
|
+
|
|
758
|
+
static VALUE convert_and_wrap_span(VALUE arg) {
|
|
759
|
+
wrap_span_ctx *ctx = (wrap_span_ctx *)arg;
|
|
760
|
+
convert_ruby_span_to_rust(ctx->span, &ctx->owner);
|
|
761
|
+
|
|
762
|
+
VALUE wrapped = TypedData_Wrap_Struct(
|
|
763
|
+
tracer_span_class, &tracer_span_typed_data, ctx->owner.span);
|
|
764
|
+
ctx->owner.span = NULL;
|
|
765
|
+
return wrapped;
|
|
766
|
+
}
|
|
767
|
+
|
|
430
768
|
static VALUE _native_from_span(DDTRACE_UNUSED VALUE klass, VALUE span) {
|
|
431
|
-
|
|
432
|
-
return
|
|
433
|
-
|
|
769
|
+
wrap_span_ctx ctx = {.span = span, .owner = {.span = NULL}};
|
|
770
|
+
return rb_ensure(
|
|
771
|
+
convert_and_wrap_span, (VALUE)&ctx,
|
|
772
|
+
free_raw_span, (VALUE)&ctx.owner);
|
|
434
773
|
}
|
|
435
774
|
|
|
436
775
|
/* ========================================================================
|
|
@@ -516,17 +855,27 @@ static VALUE _native_exporter_new(
|
|
|
516
855
|
if (rb_service != Qnil) ENFORCE_TYPE(rb_service, T_STRING);
|
|
517
856
|
if (rb_version != Qnil) ENFORCE_TYPE(rb_version, T_STRING);
|
|
518
857
|
|
|
519
|
-
/* Phase 2:
|
|
858
|
+
/* Phase 2: configure before creating the separately-owned runtime. */
|
|
520
859
|
ddog_TraceExporterConfig *config = NULL;
|
|
521
860
|
ddog_trace_exporter_config_new(&config);
|
|
522
861
|
|
|
862
|
+
set_config_field(config, ddog_trace_exporter_config_set_url, rb_url, "url");
|
|
863
|
+
set_config_field(config, ddog_trace_exporter_config_set_tracer_version, rb_tracer_version, "tracer_version");
|
|
864
|
+
set_config_field(config, ddog_trace_exporter_config_set_language, rb_language, "language");
|
|
865
|
+
set_config_field(config, ddog_trace_exporter_config_set_lang_version, rb_language_version, "language_version");
|
|
866
|
+
set_config_field(config, ddog_trace_exporter_config_set_lang_interpreter, rb_language_interpreter, "language_interpreter");
|
|
867
|
+
set_config_field(config, ddog_trace_exporter_config_set_hostname, rb_hostname, "hostname");
|
|
868
|
+
set_config_field(config, ddog_trace_exporter_config_set_env, rb_env, "env");
|
|
869
|
+
set_config_field(config, ddog_trace_exporter_config_set_service, rb_service, "service");
|
|
870
|
+
set_config_field(config, ddog_trace_exporter_config_set_version, rb_version, "version");
|
|
871
|
+
|
|
523
872
|
/*
|
|
524
873
|
* Create a SharedRuntime and attach it to the config before building the
|
|
525
874
|
* exporter. The exporter holds a clone of the runtime's Arc; we keep our
|
|
526
875
|
* own handle in the wrapper to drive fork-safety hooks and to free it when
|
|
527
876
|
* the exporter is collected.
|
|
528
877
|
*/
|
|
529
|
-
const
|
|
878
|
+
const ddog_ForkSafeRuntime *runtime = NULL;
|
|
530
879
|
ddog_SharedRuntimeFFIError *rt_err = ddog_shared_runtime_new(&runtime);
|
|
531
880
|
if (rt_err != NULL) {
|
|
532
881
|
ddog_trace_exporter_config_free(config);
|
|
@@ -534,13 +883,13 @@ static VALUE _native_exporter_new(
|
|
|
534
883
|
}
|
|
535
884
|
|
|
536
885
|
/*
|
|
537
|
-
* Const asymmetry: ddog_shared_runtime_new yields a `const
|
|
886
|
+
* Const asymmetry: ddog_shared_runtime_new yields a `const ddog_ForkSafeRuntime *`
|
|
538
887
|
* but the setter takes a non-const pointer. The setter only clones the Arc,
|
|
539
888
|
* so casting away const here is safe.
|
|
540
889
|
*/
|
|
541
890
|
{
|
|
542
891
|
ddog_TraceExporterError *attach_err = ddog_trace_exporter_config_set_shared_runtime(
|
|
543
|
-
config, (
|
|
892
|
+
config, (ddog_ForkSafeRuntime *)runtime);
|
|
544
893
|
if (attach_err != NULL) {
|
|
545
894
|
ddog_trace_exporter_config_free(config);
|
|
546
895
|
ddog_shared_runtime_free(runtime);
|
|
@@ -548,16 +897,6 @@ static VALUE _native_exporter_new(
|
|
|
548
897
|
}
|
|
549
898
|
}
|
|
550
899
|
|
|
551
|
-
set_config_field(config, ddog_trace_exporter_config_set_url, rb_url, "url");
|
|
552
|
-
set_config_field(config, ddog_trace_exporter_config_set_tracer_version, rb_tracer_version, "tracer_version");
|
|
553
|
-
set_config_field(config, ddog_trace_exporter_config_set_language, rb_language, "language");
|
|
554
|
-
set_config_field(config, ddog_trace_exporter_config_set_lang_version, rb_language_version, "language_version");
|
|
555
|
-
set_config_field(config, ddog_trace_exporter_config_set_lang_interpreter, rb_language_interpreter, "language_interpreter");
|
|
556
|
-
set_config_field(config, ddog_trace_exporter_config_set_hostname, rb_hostname, "hostname");
|
|
557
|
-
set_config_field(config, ddog_trace_exporter_config_set_env, rb_env, "env");
|
|
558
|
-
set_config_field(config, ddog_trace_exporter_config_set_service, rb_service, "service");
|
|
559
|
-
set_config_field(config, ddog_trace_exporter_config_set_version, rb_version, "version");
|
|
560
|
-
|
|
561
900
|
/* Phase 3: build the exporter from the config */
|
|
562
901
|
ddog_TraceExporter *exporter = NULL;
|
|
563
902
|
ddog_TraceExporterError *err = ddog_trace_exporter_new(&exporter, config);
|
|
@@ -703,6 +1042,7 @@ typedef struct {
|
|
|
703
1042
|
const ddog_TraceExporter *exporter;
|
|
704
1043
|
VALUE traces;
|
|
705
1044
|
long trace_count;
|
|
1045
|
+
raw_span_owner span_owner;
|
|
706
1046
|
ddog_TracerTraceChunks *chunks; /* NULL after send consumes it */
|
|
707
1047
|
} send_traces_ctx;
|
|
708
1048
|
|
|
@@ -727,20 +1067,13 @@ static VALUE build_and_send_traces(VALUE arg) {
|
|
|
727
1067
|
ddog_tracer_trace_chunks_begin_chunk(ctx->chunks, (size_t)span_count);
|
|
728
1068
|
check_exporter_error("Failed to begin trace chunk", begin_err);
|
|
729
1069
|
for (long j = 0; j < span_count; j++) {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
* rb_ensure guarantees chunks is freed in that case. */
|
|
734
|
-
ddog_TracerSpan *rust_span = convert_ruby_span_to_rust(rb_span);
|
|
735
|
-
|
|
736
|
-
/* push_span consumes rust_span (ownership transferred to chunks).
|
|
737
|
-
* The error path should be unreachable: push only fails if no chunk was
|
|
738
|
-
* started (we always call begin_chunk above) or if the handle is NULL.
|
|
739
|
-
* Raise rather than swallow, so that if a future libdatadog change makes
|
|
740
|
-
* it reachable we find out loudly instead of silently sending a
|
|
741
|
-
* truncated chunk. rb_ensure frees chunks on the raise. */
|
|
1070
|
+
convert_ruby_span_to_rust(
|
|
1071
|
+
rb_ary_entry(chunk_spans, j), &ctx->span_owner);
|
|
1072
|
+
|
|
742
1073
|
ddog_TraceExporterError *push_err =
|
|
743
|
-
ddog_tracer_trace_chunks_push_span(ctx->chunks,
|
|
1074
|
+
ddog_tracer_trace_chunks_push_span(ctx->chunks, ctx->span_owner.span);
|
|
1075
|
+
/* push_span consumes the span on every path. */
|
|
1076
|
+
ctx->span_owner.span = NULL;
|
|
744
1077
|
check_exporter_error("Failed to push span into trace chunk", push_err);
|
|
745
1078
|
}
|
|
746
1079
|
}
|
|
@@ -834,11 +1167,12 @@ static VALUE build_and_send_traces(VALUE arg) {
|
|
|
834
1167
|
}
|
|
835
1168
|
|
|
836
1169
|
/*
|
|
837
|
-
* Ensure: free
|
|
1170
|
+
* Ensure: free the current raw span and any chunks not consumed by the send.
|
|
838
1171
|
* This runs whether build_and_send_traces returned normally or raised.
|
|
839
1172
|
*/
|
|
840
|
-
static VALUE
|
|
1173
|
+
static VALUE free_send_resources(VALUE arg) {
|
|
841
1174
|
send_traces_ctx *ctx = (send_traces_ctx *)arg;
|
|
1175
|
+
free_raw_span((VALUE)&ctx->span_owner);
|
|
842
1176
|
if (ctx->chunks != NULL) {
|
|
843
1177
|
ddog_tracer_trace_chunks_free(ctx->chunks);
|
|
844
1178
|
ctx->chunks = NULL;
|
|
@@ -877,12 +1211,13 @@ static VALUE _native_send_traces(VALUE self, VALUE traces) {
|
|
|
877
1211
|
.exporter = wrapper->exporter,
|
|
878
1212
|
.traces = traces,
|
|
879
1213
|
.trace_count = trace_count,
|
|
1214
|
+
.span_owner = {.span = NULL},
|
|
880
1215
|
.chunks = chunks,
|
|
881
1216
|
};
|
|
882
1217
|
|
|
883
1218
|
return rb_ensure(
|
|
884
1219
|
build_and_send_traces, (VALUE)&ctx,
|
|
885
|
-
|
|
1220
|
+
free_send_resources, (VALUE)&ctx);
|
|
886
1221
|
}
|
|
887
1222
|
|
|
888
1223
|
/* ========================================================================
|
|
@@ -957,9 +1292,12 @@ void trace_exporter_init(VALUE tracing_module) {
|
|
|
957
1292
|
at_status_id = rb_intern("@status");
|
|
958
1293
|
at_meta_id = rb_intern("@meta");
|
|
959
1294
|
at_metrics_id = rb_intern("@metrics");
|
|
1295
|
+
at_metastruct_id = rb_intern("@metastruct");
|
|
960
1296
|
|
|
961
1297
|
/* Methods */
|
|
962
1298
|
id_duration_method = rb_intern("duration");
|
|
1299
|
+
id_to_h = rb_intern("to_h");
|
|
1300
|
+
id_negative_p = rb_intern("negative?");
|
|
963
1301
|
|
|
964
1302
|
/* Response.new */
|
|
965
1303
|
id_new = rb_intern("new");
|
|
@@ -10,7 +10,7 @@ module Datadog
|
|
|
10
10
|
module LibdatadogExtconfHelpers
|
|
11
11
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
|
12
12
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
|
13
|
-
LIBDATADOG_VERSION = "~>
|
|
13
|
+
LIBDATADOG_VERSION = "~> 40.0.0.1.0"
|
|
14
14
|
|
|
15
15
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
|
16
16
|
# libdatadog are moved after the extension gets compiled.
|