datadog 2.21.0 → 2.22.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 +48 -1
- data/ext/LIBDATADOG_DEVELOPMENT.md +60 -0
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/libdatadog_api/ddsketch.c +106 -0
- data/ext/libdatadog_api/init.c +3 -0
- data/ext/libdatadog_api/library_config.c +35 -27
- data/ext/libdatadog_api/process_discovery.c +19 -13
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
- data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
- data/lib/datadog/appsec/compressed_json.rb +1 -1
- data/lib/datadog/appsec/configuration/settings.rb +9 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
- data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
- data/lib/datadog/appsec/event.rb +12 -14
- data/lib/datadog/appsec/metrics/collector.rb +19 -3
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
- data/lib/datadog/appsec/remote.rb +25 -13
- data/lib/datadog/appsec/security_engine/result.rb +28 -9
- data/lib/datadog/appsec/security_engine/runner.rb +17 -7
- data/lib/datadog/appsec/security_event.rb +5 -7
- data/lib/datadog/core/configuration/components.rb +14 -6
- data/lib/datadog/core/configuration/stable_config.rb +10 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +2 -0
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/ddsketch.rb +21 -0
- data/lib/datadog/core/environment/yjit.rb +2 -1
- data/lib/datadog/core/pin.rb +4 -8
- data/lib/datadog/core/process_discovery.rb +4 -2
- data/lib/datadog/core/remote/component.rb +4 -6
- data/lib/datadog/core/telemetry/component.rb +11 -0
- data/lib/datadog/core/telemetry/emitter.rb +6 -6
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
- data/lib/datadog/core/telemetry/event.rb +1 -0
- data/lib/datadog/core/transport/response.rb +4 -1
- data/lib/datadog/core/utils/network.rb +19 -0
- data/lib/datadog/di/boot.rb +1 -0
- data/lib/datadog/di/component.rb +14 -0
- data/lib/datadog/di/context.rb +70 -0
- data/lib/datadog/di/el/compiler.rb +164 -0
- data/lib/datadog/di/el/evaluator.rb +159 -0
- data/lib/datadog/di/el/expression.rb +42 -0
- data/lib/datadog/di/el.rb +5 -0
- data/lib/datadog/di/error.rb +25 -0
- data/lib/datadog/di/instrumenter.rb +101 -32
- data/lib/datadog/di/probe.rb +35 -15
- data/lib/datadog/di/probe_builder.rb +39 -1
- data/lib/datadog/di/probe_manager.rb +3 -2
- data/lib/datadog/di/probe_notification_builder.rb +50 -51
- data/lib/datadog/di/serializer.rb +151 -7
- data/lib/datadog/tracing/component.rb +6 -17
- data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
- data/lib/datadog/tracing/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/component.rb +2 -2
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +53 -28
- data/lib/datadog/tracing/metadata/ext.rb +8 -0
- data/lib/datadog/version.rb +1 -1
- metadata +22 -9
- data/ext/libdatadog_api/macos_development.md +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 495f03c8c90a6786ec765ac781553fe5197d9511586a41964382b73bb69ccca9
|
4
|
+
data.tar.gz: 81c46a4063b395a010ad1a028289b74c2d55bdaa6dff36ce61085d066a9b1a19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d4ab14bf55177e33f186c762b5156dd8cb8c17471c6277e1e0d1bce444212c98d221e00a2150fb3358203c898bb40fe431e9ebca0ef8fd22feec80758f8e922
|
7
|
+
data.tar.gz: 505dd3f5f5a08a18a95aef5cb7ae979c63bee58b22d36b8d77b21b0b5998ef775ec8c437895633355664a5ac0c31a9c2624b73ef08b63fa4154712508411b172
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,33 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [2.22.0] - 2025-10-15
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Tracing: Add GraphQL error tracking with OpenTelemetry semantics ([#4864][])
|
10
|
+
* AppSec: API Security: Add endpoint collection for Rails ([#4919][])
|
11
|
+
* AppSec: Updated WAF rules to add support for JWT analysis ([#4907][])
|
12
|
+
* AppSec: Enable Remote Configuration capabilities for fingerprinting, trace tagging and user auto-instrumentation ([#4965][])
|
13
|
+
* Dynamic Instrumentation: Support `[@duration][]`, `[@return][]` and `[@exception][]` in message templates ([#4914][])
|
14
|
+
* Dynamic Instrumentation: Report evaluation errors to the UI ([#4913][])
|
15
|
+
* Dynamic Instrumentation: Support conditions for method probes ([#4909][])
|
16
|
+
* Dynamic Instrumentation: Capture exceptions raised by instrumented methods in method probes ([#4906][])
|
17
|
+
* Dynamic Instrumentation: Add support for probe conditions for line probes ([#4861][])
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
|
21
|
+
* Core: Upgrade `libdatadog` dependency to 22.0.1 ([#4902][])
|
22
|
+
* Tracing: Add `Forwarded` header to the list of headers used for remote IP detection. ([#4969][])
|
23
|
+
* AppSec: Update `libbddwaf` to version 1.25.1.0.1 ([#4894][])
|
24
|
+
* AppSec: WAF rules can control whether traces are kept or sampled ([#4918][])
|
25
|
+
* Dynamic Instrumentation: Evaluate message templates when logging instrumented code ([#4908][])
|
26
|
+
|
27
|
+
### Fixed
|
28
|
+
|
29
|
+
* Core: Improve locking code for remote configuration worker ([#4957][])
|
30
|
+
* Dynamic Instrumentation: Emit a single log event for line probes on exception-raising lines ([#4900][])
|
31
|
+
|
5
32
|
## [2.21.0] - 2025-09-17
|
6
33
|
|
7
34
|
### Added
|
@@ -3333,7 +3360,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
3333
3360
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
3334
3361
|
|
3335
3362
|
|
3336
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
3363
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.22.0...master
|
3364
|
+
[2.22.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.21.0...v2.22.0
|
3337
3365
|
[2.21.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.20.0...v2.21.0
|
3338
3366
|
[2.20.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.19.0...v2.20.0
|
3339
3367
|
[2.19.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.18.0...v2.19.0
|
@@ -4929,12 +4957,28 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4929
4957
|
[#4838]: https://github.com/DataDog/dd-trace-rb/issues/4838
|
4930
4958
|
[#4848]: https://github.com/DataDog/dd-trace-rb/issues/4848
|
4931
4959
|
[#4851]: https://github.com/DataDog/dd-trace-rb/issues/4851
|
4960
|
+
[#4861]: https://github.com/DataDog/dd-trace-rb/issues/4861
|
4932
4961
|
[#4862]: https://github.com/DataDog/dd-trace-rb/issues/4862
|
4933
4962
|
[#4863]: https://github.com/DataDog/dd-trace-rb/issues/4863
|
4963
|
+
[#4864]: https://github.com/DataDog/dd-trace-rb/issues/4864
|
4934
4964
|
[#4877]: https://github.com/DataDog/dd-trace-rb/issues/4877
|
4935
4965
|
[#4884]: https://github.com/DataDog/dd-trace-rb/issues/4884
|
4936
4966
|
[#4887]: https://github.com/DataDog/dd-trace-rb/issues/4887
|
4937
4967
|
[#4893]: https://github.com/DataDog/dd-trace-rb/issues/4893
|
4968
|
+
[#4894]: https://github.com/DataDog/dd-trace-rb/issues/4894
|
4969
|
+
[#4900]: https://github.com/DataDog/dd-trace-rb/issues/4900
|
4970
|
+
[#4902]: https://github.com/DataDog/dd-trace-rb/issues/4902
|
4971
|
+
[#4906]: https://github.com/DataDog/dd-trace-rb/issues/4906
|
4972
|
+
[#4907]: https://github.com/DataDog/dd-trace-rb/issues/4907
|
4973
|
+
[#4908]: https://github.com/DataDog/dd-trace-rb/issues/4908
|
4974
|
+
[#4909]: https://github.com/DataDog/dd-trace-rb/issues/4909
|
4975
|
+
[#4913]: https://github.com/DataDog/dd-trace-rb/issues/4913
|
4976
|
+
[#4914]: https://github.com/DataDog/dd-trace-rb/issues/4914
|
4977
|
+
[#4918]: https://github.com/DataDog/dd-trace-rb/issues/4918
|
4978
|
+
[#4919]: https://github.com/DataDog/dd-trace-rb/issues/4919
|
4979
|
+
[#4957]: https://github.com/DataDog/dd-trace-rb/issues/4957
|
4980
|
+
[#4965]: https://github.com/DataDog/dd-trace-rb/issues/4965
|
4981
|
+
[#4969]: https://github.com/DataDog/dd-trace-rb/issues/4969
|
4938
4982
|
[@AdrianLC]: https://github.com/AdrianLC
|
4939
4983
|
[@Azure7111]: https://github.com/Azure7111
|
4940
4984
|
[@BabyGroot]: https://github.com/BabyGroot
|
@@ -4993,6 +5037,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4993
5037
|
[@dorner]: https://github.com/dorner
|
4994
5038
|
[@drcapulet]: https://github.com/drcapulet
|
4995
5039
|
[@dudo]: https://github.com/dudo
|
5040
|
+
[@duration]: https://github.com/duration
|
4996
5041
|
[@e1senh0rn]: https://github.com/e1senh0rn
|
4997
5042
|
[@ecdemis123]: https://github.com/ecdemis123
|
4998
5043
|
[@elliterate]: https://github.com/elliterate
|
@@ -5001,6 +5046,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
5001
5046
|
[@erict-square]: https://github.com/erict-square
|
5002
5047
|
[@errriclee]: https://github.com/errriclee
|
5003
5048
|
[@evan-waters]: https://github.com/evan-waters
|
5049
|
+
[@exception]: https://github.com/exception
|
5004
5050
|
[@fledman]: https://github.com/fledman
|
5005
5051
|
[@frsantos]: https://github.com/frsantos
|
5006
5052
|
[@fteem]: https://github.com/fteem
|
@@ -5058,6 +5104,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
5058
5104
|
[@rahul342]: https://github.com/rahul342
|
5059
5105
|
[@randy-girard]: https://github.com/randy-girard
|
5060
5106
|
[@renchap]: https://github.com/renchap
|
5107
|
+
[@return]: https://github.com/return
|
5061
5108
|
[@ricbartm]: https://github.com/ricbartm
|
5062
5109
|
[@roccoblues]: https://github.com/roccoblues
|
5063
5110
|
[@rqz13]: https://github.com/rqz13
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Libdatadog development
|
2
|
+
|
3
|
+
These instructions can quickly get outdated, so feel free to open an issue if they're not working (and/or ping @ivoanjo).
|
4
|
+
|
5
|
+
## Using libdatadog builds from CI or GitHub
|
6
|
+
|
7
|
+
If you're developing inside docker/natively on Linux, you can use libdatadog builds from CI and GitHub.
|
8
|
+
|
9
|
+
Here's what to do:
|
10
|
+
|
11
|
+
1. Create a folder for extracting libdatadog into based on your ruby platform (for instance inside the dd-trace-rb repo):
|
12
|
+
|
13
|
+
```bash
|
14
|
+
export DD_RUBY_PLATFORM=`ruby -e 'puts Gem::Platform.local.to_s'`
|
15
|
+
echo "Current ruby platform: $DD_RUBY_PLATFORM"
|
16
|
+
mkdir -p my-libdatadog-build/$DD_RUBY_PLATFORM
|
17
|
+
```
|
18
|
+
|
19
|
+
2. Find a libdatadog build from CI or [GitHub releases](https://github.com/DataDog/libdatadog/releases). This should match the Ruby platform seen above.
|
20
|
+
3. Extract the libdatadog build into the folder:
|
21
|
+
|
22
|
+
```bash
|
23
|
+
# In this example the build is in my downloads; notice the use of strip-components to get the correct folder structure
|
24
|
+
tar zxvf ~/Downloads/libdatadog-x86_64-unknown-linux-gnu.tar.gz -C my-libdatadog-build/$DD_RUBY_PLATFORM/ --strip-components=1
|
25
|
+
# Here's how it should look after
|
26
|
+
ls my-libdatadog-build/$DD_RUBY_PLATFORM
|
27
|
+
bin cmake include lib LICENSE LICENSE-3rdparty.yml NOTICE
|
28
|
+
```
|
29
|
+
|
30
|
+
6. Tell Ruby where to find libdatadog: ```export LIBDATADOG_VENDOR_OVERRIDE=`pwd`/my-libdatadog-build/``` (Notice no platform + use of pwd for full path here)
|
31
|
+
7. From dd-trace-rb, run `bundle exec rake clean compile`
|
32
|
+
8. For incremental builds, usually `bundle exec rake compile` is faster and `clean` is not needed
|
33
|
+
|
34
|
+
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`.
|
35
|
+
|
36
|
+
## Native development on macOS
|
37
|
+
|
38
|
+
As of this writing (August 2025), the libdatadog builds on rubygems.org only support Linux.
|
39
|
+
|
40
|
+
We don't officially support using libdatadog for Ruby on other platforms yet, but it is possible to use it for local development on macOS.
|
41
|
+
(**Note that you don't need these instructions if you develop inside docker.**)
|
42
|
+
|
43
|
+
Here's how you can do so:
|
44
|
+
|
45
|
+
1. [Install rust](https://www.rust-lang.org/tools/install)
|
46
|
+
2. Install `cbindgen`: `cargo install cbindgen`
|
47
|
+
3. Clone [libdatadog](https://github.com/datadog/libdatadog)
|
48
|
+
4. Create a folder for building into based on your ruby platform:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
export DD_RUBY_PLATFORM=`ruby -e 'puts Gem::Platform.local.to_s'`
|
52
|
+
mkdir -p my-libdatadog-build/$DD_RUBY_PLATFORM
|
53
|
+
```
|
54
|
+
|
55
|
+
5. From inside of the libdatadog repo, build libdatadog into this folder: `./build-profiling-ffi.sh my-libdatadog-build/$DD_RUBY_PLATFORM`
|
56
|
+
6. Tell Ruby where to find libdatadog: `export LIBDATADOG_VENDOR_OVERRIDE=/adjust/this/to/be/the/full/path/to/my-libdatadog-build/` (Notice no platform here)
|
57
|
+
7. From dd-trace-rb, run `bundle exec rake clean compile`
|
58
|
+
8. For incremental builds, usually `bundle exec rake compile` is faster and `clean` is not needed
|
59
|
+
|
60
|
+
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`.
|
@@ -365,7 +365,7 @@ static const rb_data_type_t sampler_typed_data = {
|
|
365
365
|
};
|
366
366
|
|
367
367
|
static VALUE _native_new(VALUE klass) {
|
368
|
-
sampler_state *state = ruby_xcalloc(sizeof(sampler_state)
|
368
|
+
sampler_state *state = ruby_xcalloc(1, sizeof(sampler_state));
|
369
369
|
|
370
370
|
long now_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
371
371
|
if (now_ns == 0) {
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <datadog/ddsketch.h>
|
3
|
+
|
4
|
+
#include "datadog_ruby_common.h"
|
5
|
+
|
6
|
+
static VALUE _native_new(VALUE klass);
|
7
|
+
static void ddsketch_free(void *ptr);
|
8
|
+
static VALUE native_add(VALUE self, VALUE point);
|
9
|
+
static VALUE native_add_with_count(VALUE self, VALUE point, VALUE count);
|
10
|
+
static VALUE native_count(VALUE self);
|
11
|
+
static VALUE native_encode(VALUE self);
|
12
|
+
NORETURN(static void raise_ddsketch_error(const char *message, ddog_VoidResult result));
|
13
|
+
|
14
|
+
void ddsketch_init(VALUE core_module) {
|
15
|
+
VALUE ddsketch_class = rb_define_class_under(core_module, "DDSketch", rb_cObject);
|
16
|
+
|
17
|
+
rb_define_alloc_func(ddsketch_class, _native_new);
|
18
|
+
rb_define_method(ddsketch_class, "add", native_add, 1);
|
19
|
+
rb_define_method(ddsketch_class, "add_with_count", native_add_with_count, 2);
|
20
|
+
rb_define_method(ddsketch_class, "count", native_count, 0);
|
21
|
+
rb_define_method(ddsketch_class, "encode", native_encode, 0);
|
22
|
+
}
|
23
|
+
|
24
|
+
// This structure is used to define a Ruby object that stores a pointer to a ddsketch_Handle_DDSketch
|
25
|
+
// See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
|
26
|
+
static const rb_data_type_t ddsketch_typed_data = {
|
27
|
+
.wrap_struct_name = "Datadog::DDSketch",
|
28
|
+
.function = {
|
29
|
+
.dmark = NULL, // We don't store references to Ruby objects so we don't need to mark any of them
|
30
|
+
.dfree = ddsketch_free,
|
31
|
+
.dsize = NULL, // We don't track memory usage (although it'd be cool if we did!)
|
32
|
+
//.dcompact = NULL, // Not needed -- we don't store references to Ruby objects
|
33
|
+
},
|
34
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
35
|
+
};
|
36
|
+
|
37
|
+
static VALUE _native_new(VALUE klass) {
|
38
|
+
ddsketch_Handle_DDSketch *state = ruby_xcalloc(1, sizeof(ddsketch_Handle_DDSketch));
|
39
|
+
|
40
|
+
*state = ddog_ddsketch_new();
|
41
|
+
|
42
|
+
return TypedData_Wrap_Struct(klass, &ddsketch_typed_data, state);
|
43
|
+
}
|
44
|
+
|
45
|
+
static void ddsketch_free(void *ptr) {
|
46
|
+
ddsketch_Handle_DDSketch *state = (ddsketch_Handle_DDSketch *) ptr;
|
47
|
+
ddog_ddsketch_drop(state);
|
48
|
+
ruby_xfree(ptr);
|
49
|
+
}
|
50
|
+
|
51
|
+
static void raise_ddsketch_error(const char *message, ddog_VoidResult result) {
|
52
|
+
rb_raise(rb_eRuntimeError, "%s: %"PRIsVALUE, message, get_error_details_and_drop(&result.err));
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE native_add(VALUE self, VALUE point) {
|
56
|
+
ddsketch_Handle_DDSketch *state;
|
57
|
+
TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
|
58
|
+
|
59
|
+
ddog_VoidResult result = ddog_ddsketch_add(state, NUM2DBL(point));
|
60
|
+
|
61
|
+
if (result.tag == DDOG_VOID_RESULT_ERR) raise_ddsketch_error("DDSketch add failed", result);
|
62
|
+
|
63
|
+
return self;
|
64
|
+
}
|
65
|
+
|
66
|
+
static VALUE native_add_with_count(VALUE self, VALUE point, VALUE count) {
|
67
|
+
ddsketch_Handle_DDSketch *state;
|
68
|
+
TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
|
69
|
+
|
70
|
+
ddog_VoidResult result = ddog_ddsketch_add_with_count(state, NUM2DBL(point), NUM2DBL(count));
|
71
|
+
|
72
|
+
if (result.tag == DDOG_VOID_RESULT_ERR) raise_ddsketch_error("DDSketch add_with_count failed", result);
|
73
|
+
|
74
|
+
return self;
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE native_count(VALUE self) {
|
78
|
+
ddsketch_Handle_DDSketch *state;
|
79
|
+
TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
|
80
|
+
|
81
|
+
double count_out;
|
82
|
+
ddog_VoidResult result = ddog_ddsketch_count(state, &count_out);
|
83
|
+
|
84
|
+
if (result.tag == DDOG_VOID_RESULT_ERR) raise_ddsketch_error("DDSketch count failed", result);
|
85
|
+
|
86
|
+
return DBL2NUM(count_out);
|
87
|
+
}
|
88
|
+
|
89
|
+
static VALUE native_encode(VALUE self) {
|
90
|
+
ddsketch_Handle_DDSketch *state;
|
91
|
+
TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
|
92
|
+
|
93
|
+
ddog_Vec_U8 encoded = ddog_ddsketch_encode(state);
|
94
|
+
|
95
|
+
// Copy into a Ruby string
|
96
|
+
VALUE bytes = rb_str_new((const char *) encoded.ptr, encoded.len);
|
97
|
+
|
98
|
+
ddog_Vec_U8_drop(encoded);
|
99
|
+
|
100
|
+
// The sketch is consumed by encode; to make this a bit more user-friendly for
|
101
|
+
// a Ruby API (since we can't "kill" the Ruby object), let's re-initialize it so
|
102
|
+
// it can be used again.
|
103
|
+
*state = ddog_ddsketch_new();
|
104
|
+
|
105
|
+
return bytes;
|
106
|
+
}
|
data/ext/libdatadog_api/init.c
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
#include "process_discovery.h"
|
6
6
|
#include "library_config.h"
|
7
7
|
|
8
|
+
void ddsketch_init(VALUE core_module);
|
9
|
+
|
8
10
|
void DDTRACE_EXPORT Init_libdatadog_api(void) {
|
9
11
|
VALUE datadog_module = rb_define_module("Datadog");
|
10
12
|
VALUE core_module = rb_define_module_under(datadog_module, "Core");
|
@@ -12,4 +14,5 @@ void DDTRACE_EXPORT Init_libdatadog_api(void) {
|
|
12
14
|
crashtracker_init(core_module);
|
13
15
|
process_discovery_init(core_module);
|
14
16
|
library_config_init(core_module);
|
17
|
+
ddsketch_init(core_module);
|
15
18
|
}
|
@@ -11,7 +11,7 @@ static VALUE _native_configurator_get(VALUE self);
|
|
11
11
|
static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
12
12
|
static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
13
13
|
|
14
|
-
static VALUE
|
14
|
+
static VALUE config_logged_result_class = Qnil;
|
15
15
|
|
16
16
|
// ddog_Configurator memory management
|
17
17
|
static void configurator_free(void *configurator_ptr) {
|
@@ -29,29 +29,29 @@ static const rb_data_type_t configurator_typed_data = {
|
|
29
29
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
30
30
|
};
|
31
31
|
|
32
|
-
//
|
33
|
-
static void
|
34
|
-
|
32
|
+
// ddog_LibraryConfigLoggedResult memory management
|
33
|
+
static void config_logged_result_free(void *config_logged_result_ptr) {
|
34
|
+
ddog_LibraryConfigLoggedResult *config_logged_result = (ddog_LibraryConfigLoggedResult *)config_logged_result_ptr;
|
35
35
|
|
36
|
-
ddog_library_config_drop(*
|
37
|
-
ruby_xfree(
|
36
|
+
ddog_library_config_drop(*config_logged_result);
|
37
|
+
ruby_xfree(config_logged_result_ptr);
|
38
38
|
}
|
39
39
|
|
40
|
-
static const rb_data_type_t
|
41
|
-
.wrap_struct_name = "Datadog::Core::Configuration::
|
40
|
+
static const rb_data_type_t config_logged_result_typed_data = {
|
41
|
+
.wrap_struct_name = "Datadog::Core::Configuration::StableConfigLoggedResult",
|
42
42
|
.function = {
|
43
|
-
.dfree =
|
43
|
+
.dfree = config_logged_result_free,
|
44
44
|
.dsize = NULL,
|
45
45
|
},
|
46
46
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
47
47
|
};
|
48
48
|
|
49
49
|
void library_config_init(VALUE core_module) {
|
50
|
-
rb_global_variable(&
|
50
|
+
rb_global_variable(&config_logged_result_class);
|
51
51
|
VALUE configuration_module = rb_define_module_under(core_module, "Configuration");
|
52
52
|
VALUE stable_config_module = rb_define_module_under(configuration_module, "StableConfig");
|
53
53
|
VALUE configurator_class = rb_define_class_under(stable_config_module, "Configurator", rb_cObject);
|
54
|
-
|
54
|
+
config_logged_result_class = rb_define_class_under(configuration_module, "StableConfigLoggedResult", rb_cObject);
|
55
55
|
|
56
56
|
rb_define_alloc_func(configurator_class, _native_configurator_new);
|
57
57
|
rb_define_method(configurator_class, "get", _native_configurator_get, 0);
|
@@ -61,11 +61,12 @@ void library_config_init(VALUE core_module) {
|
|
61
61
|
rb_define_singleton_method(testing_module, "with_local_path", _native_configurator_with_local_path, 2);
|
62
62
|
rb_define_singleton_method(testing_module, "with_fleet_path", _native_configurator_with_fleet_path, 2);
|
63
63
|
|
64
|
-
rb_undef_alloc_func(
|
64
|
+
rb_undef_alloc_func(config_logged_result_class); // It cannot be created from Ruby code and only serves as an intermediate object for the Ruby GC
|
65
65
|
}
|
66
66
|
|
67
67
|
static VALUE _native_configurator_new(VALUE klass) {
|
68
|
-
|
68
|
+
// We always collect debug logs, so if DD_TRACE_DEBUG is set by stable config, we'll be able to log them.
|
69
|
+
ddog_Configurator *configurator = ddog_library_configurator_new(true, DDOG_CHARSLICE_C("ruby"));
|
69
70
|
|
70
71
|
ddog_library_configurator_with_detect_process_info(configurator);
|
71
72
|
|
@@ -98,27 +99,33 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
98
99
|
ddog_Configurator *configurator;
|
99
100
|
TypedData_Get_Struct(self, ddog_Configurator, &configurator_typed_data, configurator);
|
100
101
|
|
101
|
-
|
102
|
+
// Wrapping config_logged_result into a Ruby object enables the Ruby GC to manage its memory
|
103
|
+
// We need to allocate memory for config_logged_result because once it is out of scope, it will be freed (at the end of this function)
|
104
|
+
// So we cannot reference it with &config_logged_result
|
105
|
+
// We are doing this in case one of the ruby API raises an exception before the end of this function,
|
106
|
+
// so the allocated memory will still be freed
|
107
|
+
ddog_LibraryConfigLoggedResult *configurator_logged_result = ruby_xcalloc(1, sizeof(ddog_LibraryConfigLoggedResult));
|
108
|
+
*configurator_logged_result = ddog_library_configurator_get(configurator);
|
109
|
+
VALUE config_logged_result_rb = TypedData_Wrap_Struct(config_logged_result_class, &config_logged_result_typed_data, configurator_logged_result);
|
102
110
|
|
103
|
-
if (
|
104
|
-
ddog_Error err =
|
111
|
+
if (configurator_logged_result->tag == DDOG_LIBRARY_CONFIG_LOGGED_RESULT_ERR) {
|
112
|
+
ddog_Error err = configurator_logged_result->err;
|
105
113
|
VALUE message = get_error_details_and_drop(&err);
|
106
114
|
if (is_config_loaded()) {
|
107
115
|
log_warning(message);
|
108
116
|
} else {
|
109
117
|
log_warning_without_config(message);
|
110
118
|
}
|
119
|
+
RB_GC_GUARD(config_logged_result_rb);
|
111
120
|
return rb_hash_new();
|
112
121
|
}
|
113
122
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
ddog_Vec_LibraryConfig
|
120
|
-
*config_vec = configurator_result.ok;
|
121
|
-
VALUE config_vec_rb = TypedData_Wrap_Struct(config_vec_class, &config_vec_typed_data, config_vec);
|
123
|
+
VALUE logs = Qnil;
|
124
|
+
if (configurator_logged_result->ok.logs.length > 0) {
|
125
|
+
logs = rb_utf8_str_new_cstr(configurator_logged_result->ok.logs.ptr);
|
126
|
+
}
|
127
|
+
|
128
|
+
ddog_Vec_LibraryConfig config_vec = configurator_logged_result->ok.value;
|
122
129
|
|
123
130
|
VALUE local_config_hash = rb_hash_new();
|
124
131
|
VALUE fleet_config_hash = rb_hash_new();
|
@@ -127,8 +134,8 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
127
134
|
bool fleet_config_id_set = false;
|
128
135
|
VALUE local_hash = rb_hash_new();
|
129
136
|
VALUE fleet_hash = rb_hash_new();
|
130
|
-
for (uintptr_t i = 0; i < config_vec
|
131
|
-
ddog_LibraryConfig config = config_vec
|
137
|
+
for (uintptr_t i = 0; i < config_vec.len; i++) {
|
138
|
+
ddog_LibraryConfig config = config_vec.ptr[i];
|
132
139
|
VALUE selected_hash;
|
133
140
|
if (config.source == DDOG_LIBRARY_CONFIG_SOURCE_LOCAL_STABLE_CONFIG) {
|
134
141
|
selected_hash = local_config_hash;
|
@@ -156,9 +163,10 @@ static VALUE _native_configurator_get(VALUE self) {
|
|
156
163
|
rb_hash_aset(fleet_hash, ID2SYM(rb_intern("config")), fleet_config_hash);
|
157
164
|
|
158
165
|
VALUE result = rb_hash_new();
|
166
|
+
rb_hash_aset(result, ID2SYM(rb_intern("logs")), logs);
|
159
167
|
rb_hash_aset(result, ID2SYM(rb_intern("local")), local_hash);
|
160
168
|
rb_hash_aset(result, ID2SYM(rb_intern("fleet")), fleet_hash);
|
161
169
|
|
162
|
-
RB_GC_GUARD(
|
170
|
+
RB_GC_GUARD(config_logged_result_rb);
|
163
171
|
return result;
|
164
172
|
}
|
@@ -42,7 +42,6 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
42
42
|
rb_scan_args(argc, argv, "1:", &logger, &options);
|
43
43
|
if (options == Qnil) options = rb_hash_new();
|
44
44
|
|
45
|
-
VALUE schema_version = rb_hash_fetch(options, ID2SYM(rb_intern("schema_version")));
|
46
45
|
VALUE runtime_id = rb_hash_fetch(options, ID2SYM(rb_intern("runtime_id")));
|
47
46
|
VALUE tracer_language = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_language")));
|
48
47
|
VALUE tracer_version = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_version")));
|
@@ -50,8 +49,9 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
50
49
|
VALUE service_name = rb_hash_fetch(options, ID2SYM(rb_intern("service_name")));
|
51
50
|
VALUE service_env = rb_hash_fetch(options, ID2SYM(rb_intern("service_env")));
|
52
51
|
VALUE service_version = rb_hash_fetch(options, ID2SYM(rb_intern("service_version")));
|
52
|
+
VALUE process_tags = rb_hash_fetch(options, ID2SYM(rb_intern("process_tags")));
|
53
|
+
VALUE container_id = rb_hash_fetch(options, ID2SYM(rb_intern("container_id")));
|
53
54
|
|
54
|
-
ENFORCE_TYPE(schema_version, T_FIXNUM);
|
55
55
|
ENFORCE_TYPE(runtime_id, T_STRING);
|
56
56
|
ENFORCE_TYPE(tracer_language, T_STRING);
|
57
57
|
ENFORCE_TYPE(tracer_version, T_STRING);
|
@@ -59,17 +59,23 @@ static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
|
59
59
|
ENFORCE_TYPE(service_name, T_STRING);
|
60
60
|
ENFORCE_TYPE(service_env, T_STRING);
|
61
61
|
ENFORCE_TYPE(service_version, T_STRING);
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
);
|
62
|
+
ENFORCE_TYPE(process_tags, T_STRING);
|
63
|
+
ENFORCE_TYPE(container_id, T_STRING);
|
64
|
+
|
65
|
+
void* builder = ddog_tracer_metadata_new();
|
66
|
+
|
67
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_RUNTIME_ID, StringValueCStr(runtime_id));
|
68
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_TRACER_LANGUAGE, StringValueCStr(tracer_language));
|
69
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_TRACER_VERSION, StringValueCStr(tracer_version));
|
70
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_HOSTNAME, StringValueCStr(hostname));
|
71
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_SERVICE_NAME, StringValueCStr(service_name));
|
72
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_SERVICE_ENV, StringValueCStr(service_env));
|
73
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_SERVICE_VERSION, StringValueCStr(service_version));
|
74
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_PROCESS_TAGS, StringValueCStr(process_tags));
|
75
|
+
ddog_tracer_metadata_set(builder, DDOG_METADATA_KIND_CONTAINER_ID, StringValueCStr(container_id));
|
76
|
+
|
77
|
+
ddog_Result_TracerMemfdHandle result = ddog_tracer_metadata_store(builder);
|
78
|
+
ddog_tracer_metadata_free(builder);
|
73
79
|
|
74
80
|
if (result.tag == DDOG_RESULT_TRACER_MEMFD_HANDLE_ERR_TRACER_MEMFD_HANDLE) {
|
75
81
|
rb_funcall(logger, rb_intern("debug"), 1, rb_sprintf("Failed to store the tracer configuration in a memory file descriptor: %"PRIsVALUE, get_error_details_and_drop(&result.err)));
|
@@ -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 = '~> 22.0.1.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.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module APISecurity
|
6
|
+
module EndpointCollection
|
7
|
+
# This module serializes Grape routes.
|
8
|
+
module GrapeRouteSerializer
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def serialize(route, path_prefix: '')
|
12
|
+
path = path_prefix + route.pattern.origin
|
13
|
+
|
14
|
+
{
|
15
|
+
type: "REST",
|
16
|
+
resource_name: "#{route.request_method} #{path}",
|
17
|
+
operation_name: "http.request",
|
18
|
+
method: route.request_method,
|
19
|
+
path: path
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'rails_route_serializer'
|
4
|
+
require_relative 'grape_route_serializer'
|
5
|
+
require_relative 'sinatra_route_serializer'
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module AppSec
|
9
|
+
module APISecurity
|
10
|
+
module EndpointCollection
|
11
|
+
# This class works with a collection of rails routes
|
12
|
+
# and produces an Enumerator that yields serialized endpoints.
|
13
|
+
class RailsCollector
|
14
|
+
def initialize(routes)
|
15
|
+
@routes = routes
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_enum
|
19
|
+
Enumerator.new do |yielder|
|
20
|
+
@routes.each do |route|
|
21
|
+
if route.dispatcher?
|
22
|
+
yielder.yield RailsRouteSerializer.serialize(route)
|
23
|
+
elsif mounted_grape_app?(route.app.rack_app)
|
24
|
+
route.app.rack_app.routes.each do |grape_route|
|
25
|
+
yielder.yield GrapeRouteSerializer.serialize(grape_route, path_prefix: route.path.spec.to_s)
|
26
|
+
end
|
27
|
+
elsif mounted_sinatra_app?(route.app.rack_app)
|
28
|
+
route.app.rack_app.routes.each do |method, sinatra_routes|
|
29
|
+
next if method == 'HEAD'
|
30
|
+
|
31
|
+
sinatra_routes.each do |sinatra_route, _, _|
|
32
|
+
yielder.yield SinatraRouteSerializer.serialize(
|
33
|
+
sinatra_route, method: method, path_prefix: route.path.spec.to_s
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def mounted_grape_app?(rack_app)
|
45
|
+
return false unless defined?(::Grape::API)
|
46
|
+
|
47
|
+
rack_app.is_a?(Class) && rack_app < ::Grape::API
|
48
|
+
end
|
49
|
+
|
50
|
+
def mounted_sinatra_app?(rack_app)
|
51
|
+
return false unless defined?(::Sinatra::Base)
|
52
|
+
|
53
|
+
rack_app.is_a?(Class) && rack_app < ::Sinatra::Base
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module APISecurity
|
6
|
+
module EndpointCollection
|
7
|
+
# This module serializes Rails Journey Router routes.
|
8
|
+
module RailsRouteSerializer
|
9
|
+
FORMAT_SUFFIX = "(.:format)"
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
def serialize(route)
|
14
|
+
method = route.verb.empty? ? "*" : route.verb
|
15
|
+
path = route.path.spec.to_s.delete_suffix(FORMAT_SUFFIX)
|
16
|
+
|
17
|
+
{
|
18
|
+
type: "REST",
|
19
|
+
resource_name: "#{method} #{path}",
|
20
|
+
operation_name: "http.request",
|
21
|
+
method: method,
|
22
|
+
path: path
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module APISecurity
|
6
|
+
module EndpointCollection
|
7
|
+
# This module serializes Sinatra routes.
|
8
|
+
module SinatraRouteSerializer
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def serialize(route, method:, path_prefix: '')
|
12
|
+
path = path_prefix + route.safe_string
|
13
|
+
|
14
|
+
{
|
15
|
+
type: "REST",
|
16
|
+
resource_name: "#{method} #{path}",
|
17
|
+
operation_name: "http.request",
|
18
|
+
method: method,
|
19
|
+
path: path
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|