datadog 2.16.0 → 2.17.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 +29 -1
- data/ext/datadog_profiling_native_extension/encoded_profile.c +22 -12
- data/ext/datadog_profiling_native_extension/encoded_profile.h +1 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +45 -72
- data/ext/datadog_profiling_native_extension/stack_recorder.c +4 -5
- data/ext/libdatadog_api/crashtracker.c +10 -3
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/lru_cache.rb +49 -0
- data/lib/datadog/appsec/api_security.rb +9 -0
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -5
- data/lib/datadog/core/configuration/components.rb +29 -20
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/option.rb +18 -18
- data/lib/datadog/core/configuration/option_definition.rb +4 -4
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +10 -10
- data/lib/datadog/core/configuration.rb +16 -16
- data/lib/datadog/core/crashtracking/component.rb +2 -1
- data/lib/datadog/core/encoding.rb +1 -1
- data/lib/datadog/core/environment/cgroup.rb +10 -12
- data/lib/datadog/core/environment/container.rb +38 -40
- data/lib/datadog/core/environment/ext.rb +6 -6
- data/lib/datadog/core/environment/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +12 -14
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client.rb +32 -31
- data/lib/datadog/core/remote/component.rb +3 -3
- data/lib/datadog/core/remote/configuration/digest.rb +7 -7
- data/lib/datadog/core/remote/configuration/path.rb +1 -1
- data/lib/datadog/core/remote/transport/http/client.rb +1 -1
- data/lib/datadog/core/remote/transport/http/config.rb +21 -5
- data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -1
- data/lib/datadog/core/runtime/metrics.rb +3 -3
- data/lib/datadog/core/telemetry/component.rb +39 -24
- data/lib/datadog/core/telemetry/emitter.rb +7 -1
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +179 -0
- data/lib/datadog/core/telemetry/event/base.rb +40 -0
- data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
- data/lib/datadog/core/telemetry/event/log.rb +76 -0
- data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
- data/lib/datadog/core/telemetry/event.rb +17 -475
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/metric.rb +3 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -2
- data/lib/datadog/core/telemetry/transport/telemetry.rb +0 -1
- data/lib/datadog/core/telemetry/worker.rb +48 -27
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/builder.rb +13 -13
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
- data/lib/datadog/core/utils/duration.rb +32 -32
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/network.rb +6 -6
- data/lib/datadog/core/utils/only_once_successful.rb +16 -5
- data/lib/datadog/core/utils/time.rb +10 -2
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
- data/lib/datadog/core/worker.rb +1 -1
- data/lib/datadog/core/workers/async.rb +9 -10
- data/lib/datadog/error_tracking/component.rb +2 -2
- data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
- data/lib/datadog/profiling/ext.rb +0 -1
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +1 -6
- data/lib/datadog/profiling/scheduler.rb +8 -1
- data/lib/datadog/profiling/tag_builder.rb +1 -5
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/version.rb +1 -1
- metadata +23 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28053ce1bca4cce2032cb068c38e99a56524e6ccecec3068c4d26d1e750f9790
|
4
|
+
data.tar.gz: 29b6b57640638184370c5176e4da94e74c9770bae8afd7884d1c2baea782350d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: caf719b7c9a2e5ee3f47ad0c3e02670b90b1f76bfa5de56c10f69169c97b827f4b9e81df822e548d1390f152f15e756c54c200e9f35904138e7c672af99ef30b
|
7
|
+
data.tar.gz: eda75252942b8c7d278bab14da78c7752b17b136a3f0bd9ed145512a64b3fb8acb110a8cbbfb280b2bcf7c558409ce83b5d311fce5f019ff34516ceb3883255c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [2.17.0] - 2025-06-02
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Tracing: Add support for Rails 8.0. ([#4455][])
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
* Core: Improve tracer error reporting when agent responds with error responses to remote configuration requests ([#4669][])
|
14
|
+
* Core: Profiling: Upgrade libdatadog dependency to version 18.1 ([#4577][])
|
15
|
+
* Dynamic Instrumentation: Improve UI reporting of application and host status ([#4678][])
|
16
|
+
* Tracing: Mark AWS integration spans as errored when AWS requests fail ([#4672][])
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
|
20
|
+
* Error Tracking: remove error tracking support on Ruby 2.6 ([#4665][])
|
21
|
+
* Profiling: Fix profiling scheduler reporting corner case during shutdown ([#4679][])
|
22
|
+
* Tracing: Fix: The `on_error` warning for HTTP instrumentations ([#4673][])
|
23
|
+
|
5
24
|
## [2.16.0] - 2025-05-19
|
6
25
|
|
7
26
|
### Added
|
@@ -3222,7 +3241,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
3222
3241
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
3223
3242
|
|
3224
3243
|
|
3225
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
3244
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.17.0...master
|
3245
|
+
[2.17.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.16.0...v2.17.0
|
3226
3246
|
[2.16.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.15.0...v2.16.0
|
3227
3247
|
[2.15.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.14.0...v2.15.0
|
3228
3248
|
[2.14.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.13.0...v2.14.0
|
@@ -4734,6 +4754,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4734
4754
|
[#4426]: https://github.com/DataDog/dd-trace-rb/issues/4426
|
4735
4755
|
[#4433]: https://github.com/DataDog/dd-trace-rb/issues/4433
|
4736
4756
|
[#4437]: https://github.com/DataDog/dd-trace-rb/issues/4437
|
4757
|
+
[#4455]: https://github.com/DataDog/dd-trace-rb/issues/4455
|
4737
4758
|
[#4473]: https://github.com/DataDog/dd-trace-rb/issues/4473
|
4738
4759
|
[#4493]: https://github.com/DataDog/dd-trace-rb/issues/4493
|
4739
4760
|
[#4497]: https://github.com/DataDog/dd-trace-rb/issues/4497
|
@@ -4752,6 +4773,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4752
4773
|
[#4568]: https://github.com/DataDog/dd-trace-rb/issues/4568
|
4753
4774
|
[#4573]: https://github.com/DataDog/dd-trace-rb/issues/4573
|
4754
4775
|
[#4575]: https://github.com/DataDog/dd-trace-rb/issues/4575
|
4776
|
+
[#4577]: https://github.com/DataDog/dd-trace-rb/issues/4577
|
4755
4777
|
[#4580]: https://github.com/DataDog/dd-trace-rb/issues/4580
|
4756
4778
|
[#4581]: https://github.com/DataDog/dd-trace-rb/issues/4581
|
4757
4779
|
[#4590]: https://github.com/DataDog/dd-trace-rb/issues/4590
|
@@ -4767,6 +4789,12 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4767
4789
|
[#4644]: https://github.com/DataDog/dd-trace-rb/issues/4644
|
4768
4790
|
[#4653]: https://github.com/DataDog/dd-trace-rb/issues/4653
|
4769
4791
|
[#4656]: https://github.com/DataDog/dd-trace-rb/issues/4656
|
4792
|
+
[#4665]: https://github.com/DataDog/dd-trace-rb/issues/4665
|
4793
|
+
[#4669]: https://github.com/DataDog/dd-trace-rb/issues/4669
|
4794
|
+
[#4672]: https://github.com/DataDog/dd-trace-rb/issues/4672
|
4795
|
+
[#4673]: https://github.com/DataDog/dd-trace-rb/issues/4673
|
4796
|
+
[#4678]: https://github.com/DataDog/dd-trace-rb/issues/4678
|
4797
|
+
[#4679]: https://github.com/DataDog/dd-trace-rb/issues/4679
|
4770
4798
|
[@AdrianLC]: https://github.com/AdrianLC
|
4771
4799
|
[@Azure7111]: https://github.com/Azure7111
|
4772
4800
|
[@BabyGroot]: https://github.com/BabyGroot
|
@@ -38,6 +38,26 @@ VALUE from_ddog_prof_EncodedProfile(ddog_prof_EncodedProfile profile) {
|
|
38
38
|
return TypedData_Wrap_Struct(encoded_profile_class, &encoded_profile_typed_data, state);
|
39
39
|
}
|
40
40
|
|
41
|
+
static ddog_ByteSlice get_bytes(ddog_prof_EncodedProfile *state) {
|
42
|
+
ddog_prof_Result_ByteSlice raw_bytes = ddog_prof_EncodedProfile_bytes(state);
|
43
|
+
if (raw_bytes.tag == DDOG_PROF_RESULT_BYTE_SLICE_ERR_BYTE_SLICE) {
|
44
|
+
rb_raise(rb_eRuntimeError, "Failed to get bytes from profile: %"PRIsVALUE, get_error_details_and_drop(&raw_bytes.err));
|
45
|
+
}
|
46
|
+
return raw_bytes.ok;
|
47
|
+
}
|
48
|
+
|
49
|
+
static ddog_prof_EncodedProfile *internal_to_ddog_prof_EncodedProfile(VALUE object) {
|
50
|
+
ddog_prof_EncodedProfile *state;
|
51
|
+
TypedData_Get_Struct(object, ddog_prof_EncodedProfile, &encoded_profile_typed_data, state);
|
52
|
+
return state;
|
53
|
+
}
|
54
|
+
|
55
|
+
ddog_prof_EncodedProfile *to_ddog_prof_EncodedProfile(VALUE object) {
|
56
|
+
ddog_prof_EncodedProfile *state = internal_to_ddog_prof_EncodedProfile(object);
|
57
|
+
get_bytes(state); // Validate profile is still usable -- if it's not, this will raise an exception
|
58
|
+
return state;
|
59
|
+
}
|
60
|
+
|
41
61
|
static void encoded_profile_typed_data_free(void *state_ptr) {
|
42
62
|
ddog_prof_EncodedProfile *state = (ddog_prof_EncodedProfile *) state_ptr;
|
43
63
|
|
@@ -49,18 +69,8 @@ static void encoded_profile_typed_data_free(void *state_ptr) {
|
|
49
69
|
}
|
50
70
|
|
51
71
|
static VALUE _native_bytes(VALUE self) {
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
return ruby_string_from_vec_u8(state->buffer);
|
56
|
-
|
57
|
-
// TODO: This will be used for libdatadog 17
|
58
|
-
/*ddog_prof_Result_ByteSlice raw_bytes = ddog_prof_EncodedProfile_bytes(state);
|
59
|
-
if (raw_bytes.tag == DDOG_PROF_RESULT_BYTE_SLICE_ERR_BYTE_SLICE) {
|
60
|
-
rb_raise(rb_eRuntimeError, "Failed to get bytes from profile: %"PRIsVALUE, get_error_details_and_drop(&raw_bytes.err));
|
61
|
-
}
|
62
|
-
|
63
|
-
return rb_str_new((const char *) raw_bytes.ok.ptr, raw_bytes.ok.len);*/
|
72
|
+
ddog_ByteSlice bytes = get_bytes(internal_to_ddog_prof_EncodedProfile(self));
|
73
|
+
return rb_str_new((const char *) bytes.ptr, bytes.len);
|
64
74
|
}
|
65
75
|
|
66
76
|
VALUE enforce_encoded_profile_instance(VALUE object) {
|
@@ -15,26 +15,22 @@ static VALUE error_symbol = Qnil; // :error in Ruby
|
|
15
15
|
static VALUE library_version_string = Qnil;
|
16
16
|
|
17
17
|
typedef struct {
|
18
|
-
|
19
|
-
|
18
|
+
ddog_prof_ProfileExporter *exporter;
|
19
|
+
ddog_prof_Request_Result *build_result;
|
20
20
|
ddog_CancellationToken *cancel_token;
|
21
|
-
|
21
|
+
ddog_prof_Result_HttpStatus result;
|
22
22
|
bool send_ran;
|
23
23
|
} call_exporter_without_gvl_arguments;
|
24
24
|
|
25
25
|
static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
|
26
26
|
static VALUE _native_validate_exporter(VALUE self, VALUE exporter_configuration);
|
27
|
-
static
|
28
|
-
static VALUE handle_exporter_failure(
|
27
|
+
static ddog_prof_ProfileExporter_Result create_exporter(VALUE exporter_configuration, VALUE tags_as_array);
|
28
|
+
static VALUE handle_exporter_failure(ddog_prof_ProfileExporter_Result exporter_result);
|
29
29
|
static VALUE _native_do_export(
|
30
30
|
VALUE self,
|
31
31
|
VALUE exporter_configuration,
|
32
32
|
VALUE upload_timeout_milliseconds,
|
33
|
-
VALUE flush
|
34
|
-
VALUE start_timespec_seconds,
|
35
|
-
VALUE start_timespec_nanoseconds,
|
36
|
-
VALUE finish_timespec_seconds,
|
37
|
-
VALUE finish_timespec_nanoseconds
|
33
|
+
VALUE flush
|
38
34
|
);
|
39
35
|
static void *call_exporter_without_gvl(void *call_args);
|
40
36
|
static void interrupt_exporter_call(void *cancel_token);
|
@@ -43,7 +39,7 @@ void http_transport_init(VALUE profiling_module) {
|
|
43
39
|
VALUE http_transport_class = rb_define_class_under(profiling_module, "HttpTransport", rb_cObject);
|
44
40
|
|
45
41
|
rb_define_singleton_method(http_transport_class, "_native_validate_exporter", _native_validate_exporter, 1);
|
46
|
-
rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export,
|
42
|
+
rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 3);
|
47
43
|
|
48
44
|
ok_symbol = ID2SYM(rb_intern_const("ok"));
|
49
45
|
error_symbol = ID2SYM(rb_intern_const("error"));
|
@@ -60,14 +56,14 @@ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
|
|
60
56
|
|
61
57
|
static VALUE _native_validate_exporter(DDTRACE_UNUSED VALUE _self, VALUE exporter_configuration) {
|
62
58
|
ENFORCE_TYPE(exporter_configuration, T_ARRAY);
|
63
|
-
|
59
|
+
ddog_prof_ProfileExporter_Result exporter_result = create_exporter(exporter_configuration, rb_ary_new());
|
64
60
|
|
65
61
|
VALUE failure_tuple = handle_exporter_failure(exporter_result);
|
66
62
|
if (!NIL_P(failure_tuple)) return failure_tuple;
|
67
63
|
|
68
64
|
// We don't actually need the exporter for now -- we just wanted to validate that we could create it with the
|
69
65
|
// settings we were given
|
70
|
-
ddog_prof_Exporter_drop(exporter_result.ok);
|
66
|
+
ddog_prof_Exporter_drop(&exporter_result.ok);
|
71
67
|
|
72
68
|
return rb_ary_new_from_args(2, ok_symbol, Qnil);
|
73
69
|
}
|
@@ -93,7 +89,7 @@ static ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
|
|
93
89
|
}
|
94
90
|
}
|
95
91
|
|
96
|
-
static
|
92
|
+
static ddog_prof_ProfileExporter_Result create_exporter(VALUE exporter_configuration, VALUE tags_as_array) {
|
97
93
|
ENFORCE_TYPE(exporter_configuration, T_ARRAY);
|
98
94
|
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
99
95
|
|
@@ -107,7 +103,7 @@ static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration
|
|
107
103
|
ddog_CharSlice library_version = char_slice_from_ruby_string(library_version_string);
|
108
104
|
ddog_CharSlice profiling_family = DDOG_CHARSLICE_C("ruby");
|
109
105
|
|
110
|
-
|
106
|
+
ddog_prof_ProfileExporter_Result exporter_result =
|
111
107
|
ddog_prof_Exporter_new(library_name, library_version, profiling_family, &tags, endpoint);
|
112
108
|
|
113
109
|
ddog_Vec_Tag_drop(tags);
|
@@ -115,8 +111,12 @@ static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration
|
|
115
111
|
return exporter_result;
|
116
112
|
}
|
117
113
|
|
118
|
-
static
|
119
|
-
|
114
|
+
static void validate_token(ddog_CancellationToken token, const char *file, int line) {
|
115
|
+
if (token.inner == NULL) rb_raise(rb_eRuntimeError, "Unexpected: Validation token was empty at %s:%d", file, line);
|
116
|
+
}
|
117
|
+
|
118
|
+
static VALUE handle_exporter_failure(ddog_prof_ProfileExporter_Result exporter_result) {
|
119
|
+
return exporter_result.tag == DDOG_PROF_PROFILE_EXPORTER_RESULT_OK_HANDLE_PROFILE_EXPORTER ?
|
120
120
|
Qnil :
|
121
121
|
rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&exporter_result.err));
|
122
122
|
}
|
@@ -124,38 +124,37 @@ static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_resul
|
|
124
124
|
// Note: This function handles a bunch of libdatadog dynamically-allocated objects, so it MUST not use any Ruby APIs
|
125
125
|
// which can raise exceptions, otherwise the objects will be leaked.
|
126
126
|
static VALUE perform_export(
|
127
|
-
|
128
|
-
|
129
|
-
ddog_Timespec finish,
|
127
|
+
ddog_prof_ProfileExporter *exporter,
|
128
|
+
ddog_prof_EncodedProfile *profile,
|
130
129
|
ddog_prof_Exporter_Slice_File files_to_compress_and_export,
|
131
|
-
ddog_prof_Exporter_Slice_File files_to_export_unmodified,
|
132
130
|
ddog_CharSlice internal_metadata,
|
133
131
|
ddog_CharSlice info
|
134
132
|
) {
|
135
|
-
|
136
|
-
ddog_prof_Exporter_Request_BuildResult build_result = ddog_prof_Exporter_Request_build(
|
133
|
+
ddog_prof_Request_Result build_result = ddog_prof_Exporter_Request_build(
|
137
134
|
exporter,
|
138
|
-
|
139
|
-
finish,
|
135
|
+
profile,
|
140
136
|
files_to_compress_and_export,
|
141
|
-
files_to_export_unmodified,
|
137
|
+
/* files_to_export_unmodified: */ ddog_prof_Exporter_Slice_File_empty(),
|
142
138
|
/* optional_additional_tags: */ NULL,
|
143
|
-
endpoints_stats,
|
144
139
|
&internal_metadata,
|
145
140
|
&info
|
146
141
|
);
|
147
142
|
|
148
|
-
if (build_result.tag ==
|
143
|
+
if (build_result.tag == DDOG_PROF_REQUEST_RESULT_ERR_HANDLE_REQUEST) {
|
149
144
|
ddog_prof_Exporter_drop(exporter);
|
150
145
|
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&build_result.err));
|
151
146
|
}
|
152
147
|
|
153
|
-
ddog_CancellationToken
|
148
|
+
ddog_CancellationToken cancel_token_request = ddog_CancellationToken_new();
|
149
|
+
ddog_CancellationToken cancel_token_interrupt = ddog_CancellationToken_clone(&cancel_token_request);
|
150
|
+
|
151
|
+
validate_token(cancel_token_request, __FILE__, __LINE__);
|
152
|
+
validate_token(cancel_token_interrupt, __FILE__, __LINE__);
|
154
153
|
|
155
154
|
// We'll release the Global VM Lock while we're calling send, so that the Ruby VM can continue to work while this
|
156
155
|
// is pending
|
157
156
|
call_exporter_without_gvl_arguments args =
|
158
|
-
{.exporter = exporter, .build_result = &build_result, .cancel_token =
|
157
|
+
{.exporter = exporter, .build_result = &build_result, .cancel_token = &cancel_token_request, .send_ran = false};
|
159
158
|
|
160
159
|
// We use rb_thread_call_without_gvl2 instead of rb_thread_call_without_gvl as the gvl2 variant never raises any
|
161
160
|
// exceptions.
|
@@ -172,14 +171,15 @@ static VALUE perform_export(
|
|
172
171
|
int pending_exception = 0;
|
173
172
|
|
174
173
|
while (!args.send_ran && !pending_exception) {
|
175
|
-
rb_thread_call_without_gvl2(call_exporter_without_gvl, &args, interrupt_exporter_call,
|
174
|
+
rb_thread_call_without_gvl2(call_exporter_without_gvl, &args, interrupt_exporter_call, &cancel_token_interrupt);
|
176
175
|
|
177
176
|
// To make sure we don't leak memory, we never check for pending exceptions if send ran
|
178
177
|
if (!args.send_ran) pending_exception = check_if_pending_exception();
|
179
178
|
}
|
180
179
|
|
181
180
|
// Cleanup exporter and token, no longer needed
|
182
|
-
ddog_CancellationToken_drop(
|
181
|
+
ddog_CancellationToken_drop(&cancel_token_request);
|
182
|
+
ddog_CancellationToken_drop(&cancel_token_interrupt);
|
183
183
|
ddog_prof_Exporter_drop(exporter);
|
184
184
|
|
185
185
|
if (pending_exception) {
|
@@ -192,10 +192,10 @@ static VALUE perform_export(
|
|
192
192
|
|
193
193
|
// The request itself does not need to be freed as libdatadog takes ownership of it as part of sending.
|
194
194
|
|
195
|
-
|
195
|
+
ddog_prof_Result_HttpStatus result = args.result;
|
196
196
|
|
197
|
-
return result.tag ==
|
198
|
-
rb_ary_new_from_args(2, ok_symbol, UINT2NUM(result.
|
197
|
+
return result.tag == DDOG_PROF_RESULT_HTTP_STATUS_OK_HTTP_STATUS ?
|
198
|
+
rb_ary_new_from_args(2, ok_symbol, UINT2NUM(result.ok.code)) :
|
199
199
|
rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&result.err));
|
200
200
|
}
|
201
201
|
|
@@ -203,11 +203,7 @@ static VALUE _native_do_export(
|
|
203
203
|
DDTRACE_UNUSED VALUE _self,
|
204
204
|
VALUE exporter_configuration,
|
205
205
|
VALUE upload_timeout_milliseconds,
|
206
|
-
VALUE flush
|
207
|
-
VALUE start_timespec_seconds,
|
208
|
-
VALUE start_timespec_nanoseconds,
|
209
|
-
VALUE finish_timespec_seconds,
|
210
|
-
VALUE finish_timespec_nanoseconds
|
206
|
+
VALUE flush
|
211
207
|
) {
|
212
208
|
VALUE encoded_profile = rb_funcall(flush, rb_intern("encoded_profile"), 0);
|
213
209
|
VALUE code_provenance_file_name = rb_funcall(flush, rb_intern("code_provenance_file_name"), 0);
|
@@ -217,10 +213,6 @@ static VALUE _native_do_export(
|
|
217
213
|
VALUE info_json = rb_funcall(flush, rb_intern("info_json"), 0);
|
218
214
|
|
219
215
|
ENFORCE_TYPE(upload_timeout_milliseconds, T_FIXNUM);
|
220
|
-
ENFORCE_TYPE(start_timespec_seconds, T_FIXNUM);
|
221
|
-
ENFORCE_TYPE(start_timespec_nanoseconds, T_FIXNUM);
|
222
|
-
ENFORCE_TYPE(finish_timespec_seconds, T_FIXNUM);
|
223
|
-
ENFORCE_TYPE(finish_timespec_nanoseconds, T_FIXNUM);
|
224
216
|
enforce_encoded_profile_instance(encoded_profile);
|
225
217
|
ENFORCE_TYPE(code_provenance_file_name, T_STRING);
|
226
218
|
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
@@ -233,28 +225,9 @@ static VALUE _native_do_export(
|
|
233
225
|
|
234
226
|
uint64_t timeout_milliseconds = NUM2ULONG(upload_timeout_milliseconds);
|
235
227
|
|
236
|
-
ddog_Timespec start =
|
237
|
-
{.seconds = NUM2LONG(start_timespec_seconds), .nanoseconds = NUM2UINT(start_timespec_nanoseconds)};
|
238
|
-
ddog_Timespec finish =
|
239
|
-
{.seconds = NUM2LONG(finish_timespec_seconds), .nanoseconds = NUM2UINT(finish_timespec_nanoseconds)};
|
240
|
-
|
241
228
|
int to_compress_length = have_code_provenance ? 1 : 0;
|
242
229
|
ddog_prof_Exporter_File to_compress[to_compress_length];
|
243
|
-
int already_compressed_length = 1; // pprof
|
244
|
-
ddog_prof_Exporter_File already_compressed[already_compressed_length];
|
245
|
-
|
246
230
|
ddog_prof_Exporter_Slice_File files_to_compress_and_export = {.ptr = to_compress, .len = to_compress_length};
|
247
|
-
ddog_prof_Exporter_Slice_File files_to_export_unmodified = {.ptr = already_compressed, .len = already_compressed_length};
|
248
|
-
|
249
|
-
// TODO: Hardcoding the file name will go away with libdatadog 17
|
250
|
-
VALUE pprof_file_name = rb_str_new_cstr("rubyprofile.pprof");
|
251
|
-
VALUE pprof_data = rb_funcall(encoded_profile, rb_intern("_native_bytes"), 0);
|
252
|
-
ENFORCE_TYPE(pprof_data, T_STRING);
|
253
|
-
|
254
|
-
already_compressed[0] = (ddog_prof_Exporter_File) {
|
255
|
-
.name = char_slice_from_ruby_string(pprof_file_name),
|
256
|
-
.file = byte_slice_from_ruby_string(pprof_data),
|
257
|
-
};
|
258
231
|
|
259
232
|
if (have_code_provenance) {
|
260
233
|
to_compress[0] = (ddog_prof_Exporter_File) {
|
@@ -266,27 +239,25 @@ static VALUE _native_do_export(
|
|
266
239
|
ddog_CharSlice internal_metadata = char_slice_from_ruby_string(internal_metadata_json);
|
267
240
|
ddog_CharSlice info = char_slice_from_ruby_string(info_json);
|
268
241
|
|
269
|
-
|
242
|
+
ddog_prof_ProfileExporter_Result exporter_result = create_exporter(exporter_configuration, tags_as_array);
|
270
243
|
// Note: Do not add anything that can raise exceptions after this line, as otherwise the exporter memory will leak
|
271
244
|
|
272
245
|
VALUE failure_tuple = handle_exporter_failure(exporter_result);
|
273
246
|
if (!NIL_P(failure_tuple)) return failure_tuple;
|
274
247
|
|
275
|
-
|
276
|
-
if (timeout_result.tag ==
|
248
|
+
ddog_VoidResult timeout_result = ddog_prof_Exporter_set_timeout(&exporter_result.ok, timeout_milliseconds);
|
249
|
+
if (timeout_result.tag == DDOG_VOID_RESULT_ERR) {
|
277
250
|
// NOTE: Seems a bit harsh to fail the upload if we can't set a timeout. OTOH, this is only expected to fail
|
278
251
|
// if the exporter is not well built. Because such a situation should already be caught above I think it's
|
279
252
|
// preferable to leave this here as a virtually unreachable exception rather than ignoring it.
|
280
|
-
ddog_prof_Exporter_drop(exporter_result.ok);
|
281
|
-
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.
|
253
|
+
ddog_prof_Exporter_drop(&exporter_result.ok);
|
254
|
+
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.err));
|
282
255
|
}
|
283
256
|
|
284
257
|
return perform_export(
|
285
|
-
exporter_result.ok,
|
286
|
-
|
287
|
-
finish,
|
258
|
+
&exporter_result.ok,
|
259
|
+
to_ddog_prof_EncodedProfile(encoded_profile),
|
288
260
|
files_to_compress_and_export,
|
289
|
-
files_to_export_unmodified,
|
290
261
|
internal_metadata,
|
291
262
|
info
|
292
263
|
);
|
@@ -303,5 +274,7 @@ static void *call_exporter_without_gvl(void *call_args) {
|
|
303
274
|
|
304
275
|
// Called by Ruby when it wants to interrupt call_exporter_without_gvl above, e.g. when the app wants to exit cleanly
|
305
276
|
static void interrupt_exporter_call(void *cancel_token) {
|
277
|
+
// TODO: False here can mean two things: it was already cancelled OR it failed to cancel.
|
278
|
+
// Would be nice to change libdatadog to be able to distinguish between them...
|
306
279
|
ddog_CancellationToken_cancel((ddog_CancellationToken *) cancel_token);
|
307
280
|
}
|
@@ -363,7 +363,7 @@ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_Val
|
|
363
363
|
ddog_Timespec start_timestamp = system_epoch_now_timespec();
|
364
364
|
|
365
365
|
ddog_prof_Profile_NewResult slot_one_profile_result =
|
366
|
-
ddog_prof_Profile_new(sample_types, NULL /* period is optional
|
366
|
+
ddog_prof_Profile_new(sample_types, NULL /* period is optional */);
|
367
367
|
|
368
368
|
if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
369
369
|
rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
|
@@ -372,7 +372,7 @@ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_Val
|
|
372
372
|
state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
|
373
373
|
|
374
374
|
ddog_prof_Profile_NewResult slot_two_profile_result =
|
375
|
-
ddog_prof_Profile_new(sample_types, NULL /* period is optional
|
375
|
+
ddog_prof_Profile_new(sample_types, NULL /* period is optional */);
|
376
376
|
|
377
377
|
if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
378
378
|
// Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
|
@@ -763,7 +763,6 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
763
763
|
long serialize_no_gvl_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
764
764
|
|
765
765
|
profile_slot *slot_now_inactive = serializer_flip_active_and_inactive_slots(args->state);
|
766
|
-
|
767
766
|
args->slot = slot_now_inactive;
|
768
767
|
|
769
768
|
// Now that we have the inactive profile with all but heap samples, lets fill it with heap data
|
@@ -772,7 +771,7 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
772
771
|
args->heap_profile_build_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
|
773
772
|
|
774
773
|
// Note: The profile gets reset by the serialize call
|
775
|
-
args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->
|
774
|
+
args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->slot->start_timestamp, &args->finish_timestamp);
|
776
775
|
args->serialize_ran = true;
|
777
776
|
args->serialize_no_gvl_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
|
778
777
|
|
@@ -949,7 +948,7 @@ static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locatio
|
|
949
948
|
}
|
950
949
|
|
951
950
|
static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
|
952
|
-
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile
|
951
|
+
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile);
|
953
952
|
if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
|
954
953
|
rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
|
955
954
|
}
|
@@ -6,6 +6,8 @@
|
|
6
6
|
static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
7
7
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self);
|
8
8
|
|
9
|
+
static bool first_init = true;
|
10
|
+
|
9
11
|
// Used to report Ruby VM crashes.
|
10
12
|
// Once initialized, segfaults will be reported automatically using libdatadog.
|
11
13
|
|
@@ -62,7 +64,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
62
64
|
// "Process.kill('SEGV', Process.pid)" gets run.
|
63
65
|
//
|
64
66
|
// This actually changed in libdatadog 14, so I could see no issues with `create_alt_stack = true`, but not
|
65
|
-
//
|
67
|
+
// overriding what Ruby set up seems a saner default to keep anyway.
|
66
68
|
.create_alt_stack = false,
|
67
69
|
.use_alt_stack = true,
|
68
70
|
.endpoint = endpoint,
|
@@ -92,9 +94,14 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
92
94
|
|
93
95
|
ddog_VoidResult result =
|
94
96
|
action == start_action ?
|
95
|
-
|
97
|
+
(first_init ?
|
98
|
+
ddog_crasht_init(config, receiver_config, metadata) :
|
99
|
+
ddog_crasht_reconfigure(config, receiver_config, metadata)
|
100
|
+
) :
|
96
101
|
ddog_crasht_update_on_fork(config, receiver_config, metadata);
|
97
102
|
|
103
|
+
first_init = false;
|
104
|
+
|
98
105
|
// Clean up before potentially raising any exceptions
|
99
106
|
ddog_Vec_Tag_drop(tags);
|
100
107
|
ddog_endpoint_drop(endpoint);
|
@@ -108,7 +115,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
108
115
|
}
|
109
116
|
|
110
117
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
|
111
|
-
ddog_VoidResult result =
|
118
|
+
ddog_VoidResult result = ddog_crasht_disable();
|
112
119
|
|
113
120
|
if (result.tag == DDOG_VOID_RESULT_ERR) {
|
114
121
|
rb_raise(rb_eRuntimeError, "Failed to stop the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
|
@@ -17,9 +17,9 @@ export DD_RUBY_PLATFORM=`ruby -e 'puts Gem::Platform.local.to_s'`
|
|
17
17
|
mkdir -p my-libdatadog-build/$DD_RUBY_PLATFORM
|
18
18
|
```
|
19
19
|
|
20
|
-
5.
|
21
|
-
6. Tell
|
22
|
-
7.
|
20
|
+
5. From inside of the libdatadog repo, build libdatadog into this folder: `./build-profiling-ffi.sh my-libdatadog-build/$DD_RUBY_PLATFORM`
|
21
|
+
6. Tell Ruby where to find libdatadog: `export LIBDATADOG_VENDOR_OVERRIDE=/full/path/to/my-libdatadog-build/` (Notice no platform here)
|
22
|
+
7. From dd-trace-rb, run `bundle exec rake clean compile`
|
23
23
|
|
24
24
|
If you additionally want to run the profiler test suite, also remember to `export DD_PROFILING_MACOS_TESTING=true` and re-run `rake clean compile`.
|
25
25
|
|
@@ -8,7 +8,7 @@ module Datadog
|
|
8
8
|
module LibdatadogExtconfHelpers
|
9
9
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
10
10
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
11
|
-
LIBDATADOG_VERSION = '~>
|
11
|
+
LIBDATADOG_VERSION = '~> 18.1.0.1.0'
|
12
12
|
|
13
13
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
14
14
|
# libdatadog are moved after the extension gets compiled.
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module AppSec
|
7
|
+
module APISecurity
|
8
|
+
# An LRU (Least Recently Used) cache implementation that relies on the
|
9
|
+
# Ruby 1.9+ `Hash` implementation that guarantees insertion order.
|
10
|
+
#
|
11
|
+
# WARNING: This implementation is NOT thread-safe and should be used
|
12
|
+
# in a single-threaded context.
|
13
|
+
class LRUCache
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
def_delegators :@store, :clear, :empty?
|
17
|
+
|
18
|
+
def initialize(max_size)
|
19
|
+
raise ArgumentError, 'max_size must be an Integer' unless max_size.is_a?(Integer)
|
20
|
+
raise ArgumentError, 'max_size must be greater than 0' if max_size <= 0
|
21
|
+
|
22
|
+
@max_size = max_size
|
23
|
+
@store = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# NOTE: Accessing a key moves it to the end of the list.
|
27
|
+
def [](key)
|
28
|
+
if (entry = @store.delete(key))
|
29
|
+
@store[key] = entry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# NOTE: If the key exists, it's moved to the end of the list and
|
34
|
+
# if does not, the given block will be executed and the result
|
35
|
+
# will be stored (which will add it to the end of the list).
|
36
|
+
def fetch_or_store(key)
|
37
|
+
if (entry = @store.delete(key))
|
38
|
+
return @store[key] = entry
|
39
|
+
end
|
40
|
+
|
41
|
+
# NOTE: evict the oldest entry if store reached the maximum allowed size
|
42
|
+
@store.shift if @store.size >= @max_size
|
43
|
+
|
44
|
+
@store[key] ||= yield
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -40,7 +40,23 @@ module Datadog
|
|
40
40
|
add_all!(underflow) unless underflow.nil?
|
41
41
|
|
42
42
|
# Iteratively replace items, to ensure pseudo-random replacement.
|
43
|
-
overflow
|
43
|
+
overflow&.each { |item| replace!(item) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def unshift(*items)
|
47
|
+
# TODO The existing concat implementation does not always append
|
48
|
+
# to the end of the buffer - if the buffer is full, a random
|
49
|
+
# item is deleted and the new item is added in the position of
|
50
|
+
# removed item.
|
51
|
+
# Therefore, if we want to preserve the item order, concat
|
52
|
+
# would also need to be changed to maintain order.
|
53
|
+
# With the existing implementation, the idea is to not move
|
54
|
+
# existing items around, which is what sets unshift apart from
|
55
|
+
# concat to begin with.
|
56
|
+
#
|
57
|
+
# Since this method currently delegates to +concat+, it does not
|
58
|
+
# have a matching definition in the thread-safe worker.
|
59
|
+
concat(items)
|
44
60
|
end
|
45
61
|
|
46
62
|
# Stored items are returned and the local buffer is reset.
|
@@ -78,7 +94,7 @@ module Datadog
|
|
78
94
|
underflow = nil
|
79
95
|
overflow = nil
|
80
96
|
|
81
|
-
overflow_size = @max_size > 0 ? (@items.length + items.length) - @max_size : 0
|
97
|
+
overflow_size = (@max_size > 0) ? (@items.length + items.length) - @max_size : 0
|
82
98
|
|
83
99
|
if overflow_size > 0
|
84
100
|
# Items will overflow
|
@@ -37,8 +37,8 @@ module Datadog
|
|
37
37
|
case adapter
|
38
38
|
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
39
39
|
hostname = self.hostname
|
40
|
-
hostname = "[#{hostname}]" if hostname
|
41
|
-
"#{ssl ?
|
40
|
+
hostname = "[#{hostname}]" if IPV6_REGEXP.match?(hostname)
|
41
|
+
"#{ssl ? "https" : "http"}://#{hostname}:#{port}/"
|
42
42
|
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
|
43
43
|
"unix://#{uds_path}"
|
44
44
|
else
|
@@ -158,7 +158,7 @@ module Datadog
|
|
158
158
|
value: settings.agent.timeout_seconds,
|
159
159
|
),
|
160
160
|
try_parsing_as_integer(
|
161
|
-
friendly_name: "#{Datadog::Core::Configuration::Ext::Agent::ENV_DEFAULT_TIMEOUT_SECONDS} "\
|
161
|
+
friendly_name: "#{Datadog::Core::Configuration::Ext::Agent::ENV_DEFAULT_TIMEOUT_SECONDS} " \
|
162
162
|
'environment variable',
|
163
163
|
value: ENV[Datadog::Core::Configuration::Ext::Agent::ENV_DEFAULT_TIMEOUT_SECONDS],
|
164
164
|
)
|
@@ -338,13 +338,13 @@ module Datadog
|
|
338
338
|
log_warning(
|
339
339
|
'Configuration mismatch: values differ between ' \
|
340
340
|
"#{detected_configurations_in_priority_order
|
341
|
-
.map { |config| "#{config.friendly_name} (#{config.value.inspect})" }.join(
|
341
|
+
.map { |config| "#{config.friendly_name} (#{config.value.inspect})" }.join(" and ")}" \
|
342
342
|
". Using #{detected_configurations_in_priority_order.first.value.inspect} and ignoring other configuration."
|
343
343
|
)
|
344
344
|
end
|
345
345
|
|
346
346
|
def log_warning(message)
|
347
|
-
logger
|
347
|
+
logger&.warn(message)
|
348
348
|
end
|
349
349
|
|
350
350
|
def http_scheme?(uri)
|