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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +60 -0
  4. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  5. data/ext/libdatadog_api/ddsketch.c +106 -0
  6. data/ext/libdatadog_api/init.c +3 -0
  7. data/ext/libdatadog_api/library_config.c +35 -27
  8. data/ext/libdatadog_api/process_discovery.c +19 -13
  9. data/ext/libdatadog_extconf_helpers.rb +1 -1
  10. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  11. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
  12. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
  13. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  14. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  15. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  16. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  17. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  18. data/lib/datadog/appsec/compressed_json.rb +1 -1
  19. data/lib/datadog/appsec/configuration/settings.rb +9 -0
  20. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  21. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
  22. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
  23. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
  24. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
  25. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
  26. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
  27. data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
  28. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
  29. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
  30. data/lib/datadog/appsec/event.rb +12 -14
  31. data/lib/datadog/appsec/metrics/collector.rb +19 -3
  32. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
  33. data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
  34. data/lib/datadog/appsec/remote.rb +25 -13
  35. data/lib/datadog/appsec/security_engine/result.rb +28 -9
  36. data/lib/datadog/appsec/security_engine/runner.rb +17 -7
  37. data/lib/datadog/appsec/security_event.rb +5 -7
  38. data/lib/datadog/core/configuration/components.rb +14 -6
  39. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  40. data/lib/datadog/core/configuration/supported_configurations.rb +2 -0
  41. data/lib/datadog/core/configuration.rb +1 -1
  42. data/lib/datadog/core/ddsketch.rb +21 -0
  43. data/lib/datadog/core/environment/yjit.rb +2 -1
  44. data/lib/datadog/core/pin.rb +4 -8
  45. data/lib/datadog/core/process_discovery.rb +4 -2
  46. data/lib/datadog/core/remote/component.rb +4 -6
  47. data/lib/datadog/core/telemetry/component.rb +11 -0
  48. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  49. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  50. data/lib/datadog/core/telemetry/event.rb +1 -0
  51. data/lib/datadog/core/transport/response.rb +4 -1
  52. data/lib/datadog/core/utils/network.rb +19 -0
  53. data/lib/datadog/di/boot.rb +1 -0
  54. data/lib/datadog/di/component.rb +14 -0
  55. data/lib/datadog/di/context.rb +70 -0
  56. data/lib/datadog/di/el/compiler.rb +164 -0
  57. data/lib/datadog/di/el/evaluator.rb +159 -0
  58. data/lib/datadog/di/el/expression.rb +42 -0
  59. data/lib/datadog/di/el.rb +5 -0
  60. data/lib/datadog/di/error.rb +25 -0
  61. data/lib/datadog/di/instrumenter.rb +101 -32
  62. data/lib/datadog/di/probe.rb +35 -15
  63. data/lib/datadog/di/probe_builder.rb +39 -1
  64. data/lib/datadog/di/probe_manager.rb +3 -2
  65. data/lib/datadog/di/probe_notification_builder.rb +50 -51
  66. data/lib/datadog/di/serializer.rb +151 -7
  67. data/lib/datadog/tracing/component.rb +6 -17
  68. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  69. data/lib/datadog/tracing/configuration/settings.rb +3 -3
  70. data/lib/datadog/tracing/contrib/component.rb +2 -2
  71. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  72. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  73. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +53 -28
  74. data/lib/datadog/tracing/metadata/ext.rb +8 -0
  75. data/lib/datadog/version.rb +1 -1
  76. metadata +22 -9
  77. data/ext/libdatadog_api/macos_development.md +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e804b0ea5131eba47b865f95a6540c84a2c20e061a9d25a9bf1f2841895c46c6
4
- data.tar.gz: 7c7b61bb061c943aad519ede1f4900351db8b79e7111368c3d85f23ac73fafb8
3
+ metadata.gz: 495f03c8c90a6786ec765ac781553fe5197d9511586a41964382b73bb69ccca9
4
+ data.tar.gz: 81c46a4063b395a010ad1a028289b74c2d55bdaa6dff36ce61085d066a9b1a19
5
5
  SHA512:
6
- metadata.gz: 669cc7248fe15fbd07ab98e71d20e3ec97d644b27ef43be9b7fe7b047c60bd8794c903db3cfe1f4580f7877f7a1491f5028743a618e649930ff10d14756ae820
7
- data.tar.gz: e5a2e28ebcc390f1e2277299b883946c4f0baec35754216bbea4da4df437fa06e8c2b6cc0aa5f7847256e0b500903076a19ec7456c7979e7759fc7a4fb8836d3
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.21.0...master
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), 1);
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
+ }
@@ -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 config_vec_class = Qnil;
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
- // ddog_Vec_LibraryConfig memory management
33
- static void config_vec_free(void *config_vec_ptr) {
34
- ddog_Vec_LibraryConfig *config_vec = (ddog_Vec_LibraryConfig *)config_vec_ptr;
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(*config_vec);
37
- ruby_xfree(config_vec_ptr);
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 config_vec_typed_data = {
41
- .wrap_struct_name = "Datadog::Core::Configuration::StableConfigVec",
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 = config_vec_free,
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(&config_vec_class);
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
- config_vec_class = rb_define_class_under(configuration_module, "StableConfigVec", rb_cObject);
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(config_vec_class); // It cannot be created from Ruby code and only serves as an intermediate object for the Ruby GC
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
- ddog_Configurator *configurator = ddog_library_configurator_new(false, DDOG_CHARSLICE_C("ruby"));
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
- ddog_Result_VecLibraryConfig configurator_result = ddog_library_configurator_get(configurator);
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 (configurator_result.tag == DDOG_RESULT_VEC_LIBRARY_CONFIG_ERR_VEC_LIBRARY_CONFIG) {
104
- ddog_Error err = configurator_result.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
- // Wrapping config_vec into a Ruby object enables the Ruby GC to manage its memory
115
- // We need to allocate memory for config_vec because once it is out of scope, it will be freed (at the end of this function)
116
- // So we cannot reference it with &config_vec
117
- // We are doing this in case one of the ruby API raises an exception before the end of this function,
118
- // so the allocated memory will still be freed
119
- ddog_Vec_LibraryConfig *config_vec = ruby_xmalloc(sizeof(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->len; i++) {
131
- ddog_LibraryConfig config = config_vec->ptr[i];
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(config_vec_rb);
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
- ddog_Result_TracerMemfdHandle result = ddog_store_tracer_metadata(
64
- (uint8_t) NUM2UINT(schema_version),
65
- char_slice_from_ruby_string(runtime_id),
66
- char_slice_from_ruby_string(tracer_language),
67
- char_slice_from_ruby_string(tracer_version),
68
- char_slice_from_ruby_string(hostname),
69
- char_slice_from_ruby_string(service_name),
70
- char_slice_from_ruby_string(service_env),
71
- char_slice_from_ruby_string(service_version)
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 = '~> 18.1.0.1.0'
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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module APISecurity
6
+ module EndpointCollection
7
+ end
8
+ end
9
+ end
10
+ end