ddtrace 1.15.0 → 1.16.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18896f24a83a74a5ea6f4adfb3baad9fec922f0d3c3e8d087d28805744584d40
4
- data.tar.gz: 173d93233e49670ed94a9d3cd7501f50c596ceb7624293e4c1992513e6121fa6
3
+ metadata.gz: 31833e75aea54c0952a8c9bce646f0e75e304a3d9124f372c022a6bb5c700ea6
4
+ data.tar.gz: 6c487891f51fb0ef0c196fab1135f20d99417db62d82ee985cac621fb584f00a
5
5
  SHA512:
6
- metadata.gz: 174e727aad6f68b2873e88ac71b5a563075c501f4fbd75cad563735c765962d5753f6025a0a75c257f12a7a89fc83713e3ff249f2e2815803786ed709e35daff
7
- data.tar.gz: bc2bbcc9d601473e871dee51e53745045b37204bb902dd2f29deac2ea4c94bdc7aa6c016eecfd2648ccac13393b612400c9167bdbd115271893e561fcb12a8ce
6
+ metadata.gz: d410408162b5ac03f8f80b8a18f5bd1adbcdd70625a45d288bd2f83a38b3b4668514d70ffd57c829d2ecfc9d7c2ac147ed831ccc7f45843ab51676fe501af2be
7
+ data.tar.gz: a76c4aef579a961e0d588577d42ea23ee2ab28f08fa75d29de2fd422e3e8a5c3543e3ea63ae260ddee054c0b4ffa38c469ece4307abac92d36c08d32a971b3f2
data/CHANGELOG.md CHANGED
@@ -2,134 +2,104 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [1.15.0] - 2023-10-09
6
-
7
- ### Highlights
8
-
9
- #### Timeline view for Profiler beta
10
-
11
- As of ddtrace 1.15.0, the Profiler now supports gathering data for the new
12
- [Timeline view](https://docs.datadoghq.com/profiler/profile_visualizations/#timeline-view).
13
-
14
- The Timeline view allows you to look at time-based patterns and work distribution over the period of a single profile: you can look at what individual threads were doing, and when 🎉
15
-
16
- You can use the timeline view both when looking at individual profiles, as well as when scoped to a given trace.
17
-
18
- You can enable it:
5
+ ## [1.16.2] - 2023-11-10
19
6
 
20
- * Using an environment variable by setting `DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED=true`
21
- * Or via code by adding to your `Datadog.configure` block:
7
+ This release reverts a change to appsec response body parsing that was introduced in [1.16.0 ](https://github.com/DataDog/dd-trace-rb/releases/tag/v1.16.0) that may cause memory leaks.
22
8
 
23
- ```ruby
24
- Datadog.configure do |c|
25
- # … existing configuration …
26
- c.profiling.advanced.experimental_timeline_enabled = true
27
- end
28
- ```
9
+ ### Fixed
10
+ * Appsec: [Revert parse response body fix introduced in 1.16.0](https://github.com/DataDog/dd-trace-rb/pull/3153) ([#3252][])
29
11
 
30
- Give it a try, let us know what you think!
12
+ ## [1.16.1] - 2023-11-08
31
13
 
32
- (Note: We do not recommend enabling this feature prior to 1.15.0!)
14
+ ### Fixed
33
15
 
34
- #### google-protobuf dependency is no longer needed by the Profiler
16
+ * Tracing: Fix `concurrent-ruby` future propagation without `active_trace` ([#3242][])
17
+ * Tracing: Fix host injection error handling ([#3240][])
35
18
 
36
- As of ddtrace version 1.15.0, the `google-protobuf` gem is no longer needed to enable the Profiler.
19
+ ## [1.16.0] - 2023-11-03
37
20
 
38
- If you've added this gem to your `Gemfile`/`gems.rb` file as part of enabling the Profiler, you can
39
- remove it now. (If you're curious, we've internally replaced this dependency with the `libdatadog` gem.)
21
+ **This release includes a security change for the Tracing Redis integration:**
40
22
 
41
- #### Configure blocking responses for AppSec via configuration or Remote Configuration
23
+ Currently, the Datadog Agent removes command arguments from the resource name. However there are cases, like Redis compressed keys, where this obfuscation cannot correctly remove command arguments. To safeguard that situation, the resource name set by the tracer will only be the command (e.g. `SET`) with no arguments. To retain the previous behavior and keep arguments in the span resource, with the potential risk of some command arguments not being fully obfuscated, set ``DD_REDIS_COMMAND_ARGS=true`` or set the option `c.instrument :redis, command_args: true`.
42
24
 
43
- As of dd-trace-rb 1.15.0, AppSec supports configuring the blocking response.
25
+ ### Added
44
26
 
45
- You can configure the blocking response via:
46
- - Using the ENV variables: `DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML=#{file_name}`, and `DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON=#{file_name}`
47
- - Via code by adding to your `Datadog.configure` block:
27
+ * Tracing: Propagate trace through `Concurrent::Promises.future` ([#1522][])
28
+ * Core: Name `Datadog::Core::Remote::Worker` thread ([#3207][])
48
29
 
49
- ```ruby
50
- Datadog.configure do |c|
51
- # … existing configuration …
52
- c.appsec.block.templates.html = "#{file_name}"
53
- c.appsec.block.templates.json = "#{file_name}"
54
- end
55
- ```
30
+ ### Changed
56
31
 
57
- - Using the Remote configuration UI. This option allow you to configure the status code and the blocking behaviour. You can redirect malicious attacker to custome pages.
58
- You can find more information on the [official documentation](https://docs.datadoghq.com/security/application_security/threats/protection/#customize-protection-behavior)
32
+ * Tracing: Redis - Omit command arguments from span.resource by default ([#3235][])
33
+ * Ci-app: Bump `datadog-ci` dependency from 0.2.0 to 0.3.0 ([#3223][])
59
34
 
60
- #### Configure agentless mode for CI visibility
35
+ ### Fixed
61
36
 
62
- If you are using CI visibility with a cloud CI provider without access to the underlying worker nodes, such as GitHub Actions or CircleCI, configure the library to use the Agentless mode.
37
+ * Appsec: ASM parse response body ([#3153][])
38
+ * Appsec: ASM make sure to append content type and length information ([#3204][])
39
+ * Appsec: Make sure function that checks content-type header value accepts nil content-type header value ([#3234][])
40
+ * Profiling: Shut down profiler if any components failed ([#3197][])
41
+ * Tracing: Fix `ActiveSupport` instrumentation of custom cache stores ([#3206][])
63
42
 
64
- For this, set the following environment variables:
65
- - DD_CIVISIBILITY_AGENTLESS_ENABLED=true
66
- - DD_API_KEY=<your_api_key>
43
+ ## [1.15.0] - 2023-10-09
67
44
 
68
- Additionally, configure which Datadog site you want to send your data to:
69
- - DD_SITE (default: datadoghq.com)
45
+ ### Highlights
70
46
 
71
- You can also enable agentless mode with `Datadog.configure` block:
47
+ * Timeline view for Profiler beta
48
+ * Configure AppSec blocking responses via configuration or Remote Configuration
49
+ * CI visibility to configure with agentless mode
72
50
 
73
- ```ruby
74
- Datadog.configure do |c|
75
- # … existing configuration …
76
- c.ci.agentless_mode_enabled = true
77
- # don't forget to set DD_API_KEY env variable!
78
- end
79
- ```
51
+ For more details, check the [release notes](https://github.com/DataDog/dd-trace-rb/releases/tag/v1.15.0)
80
52
 
81
53
  ### Added
82
- * Profiling: Import java-profiler PID controller and port it to C ([#3190][])
83
- * Tracing: Support Opensearch 3 ([#3189][])
84
- * bump datadog-ci dependency to 0.2 ([#3186][])
54
+
85
55
  * Enable allocation counting feature by default for some Ruby 3 versions ([#3176][])
86
- * Tracing: Introduce async configuration for test mode to use standard writer when needed ([#3158][])
87
- * Appsec: Update AppSec rules to 1.8.0 ([#3140][])
88
- * Appsec: Update AppSec rules to 1.7.2 ([#3139][])
89
- * Appsec: ASM API security. Schema extraction ([#3131][], [#3166][], [#3177][])
90
- * Tracing: peer.service adjustment for sql propagation with DBM ([#3127][])
91
- * Ci-app: CI visibility: validate git tags ([#3100][])
92
- * Appsec: Enable configuring blocking response via Remote Configuration ([#3099][])
56
+ * Detect `WebMock` `Cucumber` and `Rails.env` to disable telemetry and remote configuration for development environment ([#3065][], [#3062][], [#3145][])
57
+ * Profiling: Import java-profiler PID controller and port it to C ([#3190][])
93
58
  * Profiling: Record allocation type when sampling objects ([#3096][])
94
- * Appsec: Uppgrade libddwaf-rb version to 1.11.0 ([#3087][])
95
- * Profiling: Mergequeue-status: removed: Include 'ruby vm type' in profiler allocation samples ([#3074][])
96
- * Detect WebMock to disable telemetry and remote configuration ([#3065][])
97
- * Ensure Rails testing is considered a development environment ([#3062][])
59
+ * Profiling: Include `ruby vm type` in profiler allocation samples ([#3074][])
60
+ * Tracing: Support `Rack` 3 ([#3132][])
61
+ * Tracing: Support `Opensearch` 3 ([#3189][])
62
+ * Tracing: `grpc` adds `client_error_handler` option ([#3095][])
63
+ * Tracing: Add `async` option for `test_mode` configuration ([#3158][])
98
64
  * Tracing: Implements `_dd.base_service` tag ([#3018][])
99
65
  * Appsec: Allow blocking response template configuration via ENV variables ([#2975][])
100
- * Ci-app: agentless mode ([#3186][])
66
+ * Appsec: ASM API security. Schema extraction ([#3131][], [#3166][], [#3177][])
67
+ * Appsec: Enable configuring blocking response via Remote Configuration ([#3099][])
68
+ * Ci-app: Validate git tags ([#3100][])
69
+ * Ci-app: Add agentless mode ([#3186][])
101
70
 
102
71
  ### Changed
103
- * Appsec: skip passing waf addresses when the value is empty ([#3188][])
104
- * Tracing: Disable memcached command tag by default ([#3171][])
105
- * Profiling: Upgrade to libdatadog 5 ([#3169][])
72
+
73
+ * Appsec: Skip passing waf addresses when the value is empty ([#3188][])
106
74
  * Profiling: Restore support for Ruby 3.3 ([#3167][])
107
- * Bump debase-ruby_core_source dependency to 3.2.2 ([#3163][])
108
75
  * Profiling: Add approximate thread state categorization for timeline ([#3162][])
109
- * Tracing: remove variable helpers module from our configuration DSL ([#3152][])
110
- * Profiling: Tracing: ekump/decouple core transport ([#3150][])
111
- * Test:Remove explicit dependency on `addressable` ([#3148][])
112
- * Detect Cucumber as a development environment ([#3145][])
113
- * Tracing: rename core configuration option on_set to after_set ([#3107][])
114
- * Profiling: Upgrade to libdatadog 4 ([#3104][])
115
76
  * Profiling: Wire up allocation sampling into `CpuAndWallTimeWorker` ([#3103][])
116
- * Tracing: rename experimental_default_proc to default_proc ([#3091][])
117
- * remove `delegate_to` configuration option from our DSL ([#3086][])
118
- * Ci-app: Fix Datadog::CI::Environment to support the new CI specs ([#3080][])
77
+ * Tracing: `dalli` disable memcached command tag by default ([#3171][])
119
78
  * Tracing: Use first valid extracted style for distributed tracing ([#2879][])
79
+ * Tracing: Rename configuration option `on_set` to `after_set` ([#3107][])
80
+ * Tracing: Rename `experimental_default_proc` to `default_proc` ([#3091][])
81
+ * Tracing: Use `peer.service` for sql comment propagation ([#3127][])
82
+ * Ci-app: Fix `Datadog::CI::Environment` to support the new CI specs ([#3080][])
83
+ * Bump `datadog-ci` dependency to 0.2 ([#3186][])
84
+ * Bump `debase-ruby_core_source` dependency to 3.2.2 ([#3163][])
85
+ * Upgrade `libdatadog` 5 ([#3169][], [#3104][])
86
+ * Upgrade `libddwaf-rb` 1.11.0 ([#3087][])
87
+ * Update AppSec rules to 1.8.0 ([#3140][], [#3139][])
120
88
 
121
89
  ### Fixed
90
+
122
91
  * Profiling: Add workaround for incorrect invoke location when logging gem is in use ([#3183][])
123
- * Profiling: Fix missing endpoint profiling when request_queuing is enabled in rack instrumentation ([#3109][])
124
- * Appsec: Fix a bug with ASM span tags reporting the number of WAF failed loaded rules ([#3106][])
92
+ * Profiling: Fix missing endpoint profiling when `request_queuing` is enabled in `rack` instrumentation ([#3109][])
93
+ * Appsec: Span tags reporting the number of WAF failed loaded rules ([#3106][])
125
94
  * Tracing: Fix tagging with empty data ([#3102][])
126
- * Tracing: fix(grpc): allow custom error_handler for client interceptor ([#3095][])
127
- * Tracing: Correctly set `rails.cache.backend` span tag for multiple stores ([#3060][])
95
+ * Tracing: Fix `rails.cache.backend` span tag with multiple stores ([#3060][])
128
96
 
129
97
  ### Removed
98
+
130
99
  * Profiling: Remove legacy profiler codepath ([#3172][])
131
- * Ci-app: remove CI module and add a dependency on datadog-ci gem ([#3128][])
132
- * Tracing: Remove `depends_on` from Core Configuration option ([#3085][])
100
+ * Ci-app: Remove CI module and add a dependency on [`datadog-ci` gem](https://github.com/DataDog/datadog-ci-rb) ([#3128][])
101
+ * Tracing: Remove `depends_on` option from configuration DSL ([#3085][])
102
+ * Tracing: Remove `delegate_to` option from configuration DSL ([#3086][])
133
103
 
134
104
  ## [1.14.0] - 2023-08-24
135
105
 
@@ -2663,7 +2633,11 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
2663
2633
 
2664
2634
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2665
2635
 
2666
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.15.0...master
2636
+
2637
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.16.2...master
2638
+ [1.16.2]: https://github.com/DataDog/dd-trace-rb/compare/v1.16.1...v1.16.2
2639
+ [1.16.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.16.0...v1.16.1
2640
+ [1.16.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.15.0...v1.16.0
2667
2641
  [1.15.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.14.0...v1.15.0
2668
2642
  [1.14.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.13.1...1.14.0
2669
2643
  [1.13.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.13.0...1.13.1
@@ -3401,6 +3375,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3401
3375
  [#1509]: https://github.com/DataDog/dd-trace-rb/issues/1509
3402
3376
  [#1510]: https://github.com/DataDog/dd-trace-rb/issues/1510
3403
3377
  [#1511]: https://github.com/DataDog/dd-trace-rb/issues/1511
3378
+ [#1522]: https://github.com/DataDog/dd-trace-rb/issues/1522
3404
3379
  [#1523]: https://github.com/DataDog/dd-trace-rb/issues/1523
3405
3380
  [#1524]: https://github.com/DataDog/dd-trace-rb/issues/1524
3406
3381
  [#1529]: https://github.com/DataDog/dd-trace-rb/issues/1529
@@ -3842,12 +3817,14 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3842
3817
  [#3127]: https://github.com/DataDog/dd-trace-rb/issues/3127
3843
3818
  [#3128]: https://github.com/DataDog/dd-trace-rb/issues/3128
3844
3819
  [#3131]: https://github.com/DataDog/dd-trace-rb/issues/3131
3820
+ [#3132]: https://github.com/DataDog/dd-trace-rb/issues/3132
3845
3821
  [#3139]: https://github.com/DataDog/dd-trace-rb/issues/3139
3846
3822
  [#3140]: https://github.com/DataDog/dd-trace-rb/issues/3140
3847
3823
  [#3145]: https://github.com/DataDog/dd-trace-rb/issues/3145
3848
3824
  [#3148]: https://github.com/DataDog/dd-trace-rb/issues/3148
3849
3825
  [#3150]: https://github.com/DataDog/dd-trace-rb/issues/3150
3850
3826
  [#3152]: https://github.com/DataDog/dd-trace-rb/issues/3152
3827
+ [#3153]: https://github.com/DataDog/dd-trace-rb/issues/3153
3851
3828
  [#3158]: https://github.com/DataDog/dd-trace-rb/issues/3158
3852
3829
  [#3162]: https://github.com/DataDog/dd-trace-rb/issues/3162
3853
3830
  [#3163]: https://github.com/DataDog/dd-trace-rb/issues/3163
@@ -3863,6 +3840,16 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3863
3840
  [#3188]: https://github.com/DataDog/dd-trace-rb/issues/3188
3864
3841
  [#3189]: https://github.com/DataDog/dd-trace-rb/issues/3189
3865
3842
  [#3190]: https://github.com/DataDog/dd-trace-rb/issues/3190
3843
+ [#3197]: https://github.com/DataDog/dd-trace-rb/issues/3197
3844
+ [#3204]: https://github.com/DataDog/dd-trace-rb/issues/3204
3845
+ [#3206]: https://github.com/DataDog/dd-trace-rb/issues/3206
3846
+ [#3207]: https://github.com/DataDog/dd-trace-rb/issues/3207
3847
+ [#3223]: https://github.com/DataDog/dd-trace-rb/issues/3223
3848
+ [#3234]: https://github.com/DataDog/dd-trace-rb/issues/3234
3849
+ [#3235]: https://github.com/DataDog/dd-trace-rb/issues/3235
3850
+ [#3240]: https://github.com/DataDog/dd-trace-rb/issues/3240
3851
+ [#3242]: https://github.com/DataDog/dd-trace-rb/issues/3242
3852
+ [#3252]: https://github.com/DataDog/dd-trace-rb/issues/3252
3866
3853
  [@AdrianLC]: https://github.com/AdrianLC
3867
3854
  [@Azure7111]: https://github.com/Azure7111
3868
3855
  [@BabyGroot]: https://github.com/BabyGroot
@@ -40,9 +40,13 @@ module Datadog
40
40
  end
41
41
 
42
42
  def headers
43
- request.env.each_with_object({}) do |(k, v), h|
44
- h[k.gsub(/^HTTP_/, '').downcase.tr('_', '-')] = v if k =~ /^HTTP_/
43
+ result = request.env.each_with_object({}) do |(k, v), h|
44
+ h[k.gsub(/^HTTP_/, '').downcase!.tr('_', '-')] = v if k =~ /^HTTP_/
45
45
  end
46
+
47
+ result['content-type'] = request.content_type if request.content_type
48
+ result['content-length'] = request.content_length if request.content_length
49
+ result
46
50
  end
47
51
 
48
52
  def body
@@ -70,7 +70,7 @@ module Datadog
70
70
  request_return[2],
71
71
  request_return[0],
72
72
  request_return[1],
73
- scope: scope
73
+ scope: scope,
74
74
  )
75
75
 
76
76
  _response_return, response_response = Instrumentation.gateway.push('rack.response', gateway_response)
@@ -330,7 +330,7 @@ module Datadog
330
330
  # Caveat 3 (severe):
331
331
  # Ruby 3.2.0 to 3.2.2 have a bug in the newobj tracepoint (https://bugs.ruby-lang.org/issues/19482,
332
332
  # https://github.com/ruby/ruby/pull/7464) so that's an extra reason why it's not safe on those Rubies.
333
- # This bug is fixed on Ruby versions 3.2.2 and 3.3.0.
333
+ # This bug is fixed on Ruby versions 3.2.3 and 3.3.0.
334
334
  #
335
335
  # @default `true` on Ruby 2.x and 3.1.4+, 3.2.3+ and 3.3.0+; `false` for Ruby 3.0 and unpatched Rubies.
336
336
  option :allocation_counting_enabled do |o|
@@ -28,7 +28,9 @@ module Datadog
28
28
 
29
29
  @starting = true
30
30
 
31
- @thr = Thread.new { poll(@interval) }
31
+ thread = Thread.new { poll(@interval) }
32
+ thread.name = self.class.name unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
33
+ @thr = thread
32
34
 
33
35
  @started = true
34
36
  @starting = false
@@ -53,7 +53,7 @@ module Datadog
53
53
  @idle_sampling_helper = idle_sampling_helper
54
54
  end
55
55
 
56
- def start
56
+ def start(on_failure_proc: nil)
57
57
  @start_stop_mutex.synchronize do
58
58
  return if @worker_thread && @worker_thread.alive?
59
59
 
@@ -74,6 +74,7 @@ module Datadog
74
74
  'CpuAndWallTimeWorker thread error. ' \
75
75
  "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
76
76
  )
77
+ on_failure_proc&.call
77
78
  end
78
79
  end
79
80
  @worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
@@ -21,18 +21,42 @@ module Datadog
21
21
  scheduler.reset_after_fork
22
22
  end
23
23
 
24
- worker.start
25
- scheduler.start
24
+ worker.start(on_failure_proc: proc { component_failed(:worker) })
25
+ scheduler.start(on_failure_proc: proc { component_failed(:scheduler) })
26
26
  end
27
27
 
28
28
  def shutdown!
29
29
  Datadog.logger.debug('Shutting down profiler')
30
30
 
31
+ stop_worker
32
+ stop_scheduler
33
+ end
34
+
35
+ private
36
+
37
+ def stop_worker
31
38
  worker.stop
39
+ end
32
40
 
41
+ def stop_scheduler
33
42
  scheduler.enabled = false
34
43
  scheduler.stop(true)
35
44
  end
45
+
46
+ def component_failed(failed_component)
47
+ Datadog.logger.warn(
48
+ "Detected issue with profiler (#{failed_component} component), stopping profiling. " \
49
+ 'See previous log messages for details.'
50
+ )
51
+
52
+ if failed_component == :worker
53
+ stop_scheduler
54
+ elsif failed_component == :scheduler
55
+ stop_worker
56
+ else
57
+ raise ArgumentError, "Unexpected failed_component: #{failed_component.inspect}"
58
+ end
59
+ end
36
60
  end
37
61
  end
38
62
  end
@@ -45,20 +45,27 @@ module Datadog
45
45
  self.enabled = enabled
46
46
  end
47
47
 
48
- def start
49
- perform
48
+ def start(on_failure_proc: nil)
49
+ perform(on_failure_proc)
50
50
  end
51
51
 
52
- def perform
53
- # A profiling flush may be called while the VM is shutting down, to report the last profile. When we do so,
54
- # we impose a strict timeout. This means this last profile may or may not be sent, depending on if the flush can
55
- # successfully finish in the strict timeout.
56
- # This can be somewhat confusing (why did it not get reported?), so let's at least log what happened.
57
- interrupted = true
58
-
52
+ def perform(on_failure_proc)
59
53
  begin
54
+ # A profiling flush may be called while the VM is shutting down, to report the last profile. When we do so,
55
+ # we impose a strict timeout. This means this last profile may or may not be sent, depending on if the flush can
56
+ # successfully finish in the strict timeout.
57
+ # This can be somewhat confusing (why did it not get reported?), so let's at least log what happened.
58
+ interrupted = true
59
+
60
60
  flush_and_wait
61
61
  interrupted = false
62
+ rescue Exception => e # rubocop:disable Lint/RescueException
63
+ Datadog.logger.warn(
64
+ 'Profiling::Scheduler thread error. ' \
65
+ "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
66
+ )
67
+ on_failure_proc&.call
68
+ raise
62
69
  ensure
63
70
  Datadog.logger.debug('#flush was interrupted or failed before it could complete') if interrupted
64
71
  end
@@ -101,7 +101,9 @@ module Datadog
101
101
 
102
102
  # DEV: String#underscore is available through ActiveSupport, and is
103
103
  # DEV: the exact reverse operation to `#camelize`.
104
- @store_name = self.class.name.underscore.match(%r{active_support/cache/(.*)})[1]
104
+ # DEV: String#demodulize is available through ActiveSupport, and is
105
+ # DEV: used to remove the module ('*::') part of a constant name.
106
+ @store_name = self.class.name.demodulize.underscore
105
107
  end
106
108
  end
107
109
 
@@ -6,7 +6,7 @@ module Datadog
6
6
  module Tracing
7
7
  module Contrib
8
8
  module ConcurrentRuby
9
- # wraps existing executor to carry over trace context
9
+ # Wraps existing executor to carry over trace context
10
10
  class ContextCompositeExecutorService
11
11
  include Concurrent::ExecutorService
12
12
 
@@ -16,20 +16,20 @@ module Datadog
16
16
  @composited_executor = composited_executor
17
17
  end
18
18
 
19
- # post method runs the task within composited executor - in a different thread
19
+ # post method runs the task within composited executor - in a different thread. The original arguments are
20
+ # captured to be propagated to the composited executor post method
20
21
  def post(*args, &task)
21
- tracer = Tracing.send(:tracer)
22
- parent_context = tracer.provider.context
23
-
24
- @composited_executor.post(*args) do
25
- begin
26
- original_context = tracer.provider.context
27
- tracer.provider.context = parent_context
28
- yield
29
- ensure
30
- # Restore context in case the current thread gets reused
31
- tracer.provider.context = original_context
32
- end
22
+ digest = Tracing.active_trace && Tracing.active_trace.to_digest
23
+ executor = @composited_executor.is_a?(Symbol) ? Concurrent.executor(@composited_executor) : @composited_executor
24
+
25
+ # Pass the original arguments to the composited executor, which
26
+ # pushes them (possibly transformed) as block args
27
+ executor.post(*args) do |*block_args|
28
+ Tracing.continue_trace!(digest)
29
+
30
+ # Pass the executor-provided block args as they should have been
31
+ # originally passed without composition, see ChainPromise#on_resolvable
32
+ yield(*block_args)
33
33
  end
34
34
  end
35
35
 
@@ -8,17 +8,10 @@ module Datadog
8
8
  module ConcurrentRuby
9
9
  # This patches the Future - to wrap executor service using ContextCompositeExecutorService
10
10
  module FuturePatch
11
- def self.included(base)
12
- base.class_eval do
13
- alias_method :ns_initialize_without_datadog, :ns_initialize
14
- remove_method(:ns_initialize)
11
+ def ns_initialize(value, opts)
12
+ super(value, opts)
15
13
 
16
- def ns_initialize(value, opts)
17
- ns_initialize_without_datadog(value, opts)
18
-
19
- @executor = ContextCompositeExecutorService.new(@executor)
20
- end
21
- end
14
+ @executor = ContextCompositeExecutorService.new(@executor)
22
15
  end
23
16
  end
24
17
  end
@@ -20,7 +20,8 @@ module Datadog
20
20
  end
21
21
 
22
22
  def self.loaded?
23
- !defined?(::Concurrent::Future).nil?
23
+ # Concurrent::Future is deprecated in favour of Concurrent::Promises::Future
24
+ !defined?(::Concurrent::Promises::Future).nil? || !defined?(::Concurrent::Future).nil?
24
25
  end
25
26
 
26
27
  def self.compatible?
@@ -19,11 +19,18 @@ module Datadog
19
19
  def patch
20
20
  require_relative 'future_patch'
21
21
  patch_future
22
+ require_relative 'promises_future_patch'
23
+ patch_promises_future
22
24
  end
23
25
 
24
26
  # Propagate tracing context in Concurrent::Future
25
27
  def patch_future
26
- ::Concurrent::Future.include(FuturePatch)
28
+ ::Concurrent::Future.prepend(FuturePatch) if defined?(::Concurrent::Future)
29
+ end
30
+
31
+ # Propagate tracing context in Concurrent::Promises::Future
32
+ def patch_promises_future
33
+ ::Concurrent::Promises.singleton_class.prepend(PromisesFuturePatch) if defined?(::Concurrent::Promises::Future)
27
34
  end
28
35
  end
29
36
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'context_composite_executor_service'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ module Contrib
8
+ module ConcurrentRuby
9
+ # This patches the Future - to wrap executor service using ContextCompositeExecutorService
10
+ module PromisesFuturePatch
11
+ def future_on(default_executor, *args, &task)
12
+ unless default_executor.is_a?(ContextCompositeExecutorService)
13
+ default_executor = ContextCompositeExecutorService.new(default_executor)
14
+ end
15
+
16
+ super(default_executor, *args, &task)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -32,7 +32,7 @@ module Datadog
32
32
  option :command_args do |o|
33
33
  o.type :bool
34
34
  o.env Ext::ENV_COMMAND_ARGS
35
- o.default true
35
+ o.default false
36
36
  end
37
37
 
38
38
  option :service_name do |o|
@@ -3,6 +3,7 @@ require_relative 'configuration/resolver'
3
3
  require_relative 'ext'
4
4
  require_relative 'quantize'
5
5
  require_relative 'tags'
6
+ require_relative 'trace_middleware'
6
7
 
7
8
  module Datadog
8
9
  module Tracing
@@ -17,31 +18,11 @@ module Datadog
17
18
  # InstanceMethods - implementing instrumentation
18
19
  module InstanceMethods
19
20
  def call(*args, &block)
20
- show_command_args = command_args?
21
-
22
- Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
23
- span.service = service_name
24
- span.span_type = Contrib::Redis::Ext::TYPE
25
- span.resource = get_command(args, show_command_args)
26
- Contrib::Redis::Tags.set_common_tags(self, span, show_command_args)
27
-
28
- super
29
- end
21
+ TraceMiddleware.call(self, args[0], service_name, command_args?) { super }
30
22
  end
31
23
 
32
24
  def call_pipeline(*args, &block)
33
- show_command_args = command_args?
34
-
35
- Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
36
- span.service = service_name
37
- span.span_type = Contrib::Redis::Ext::TYPE
38
- commands = get_pipeline_commands(args, show_command_args)
39
- span.resource = commands.any? ? commands.join("\n") : '(none)'
40
- span.set_metric Contrib::Redis::Ext::METRIC_PIPELINE_LEN, commands.length
41
- Contrib::Redis::Tags.set_common_tags(self, span, show_command_args)
42
-
43
- super
44
- end
25
+ TraceMiddleware.call_pipelined(self, args[0].commands, service_name, command_args?) { super }
45
26
  end
46
27
 
47
28
  private
@@ -59,22 +40,6 @@ module Datadog
59
40
  datadog_configuration[:service_name]
60
41
  end
61
42
 
62
- def get_command(args, show_command_args)
63
- if show_command_args
64
- Contrib::Redis::Quantize.format_command_args(*args)
65
- else
66
- Contrib::Redis::Quantize.get_verb(*args)
67
- end
68
- end
69
-
70
- def get_pipeline_commands(args, show_command_args)
71
- if show_command_args
72
- args[0].commands.map { |c| Contrib::Redis::Quantize.format_command_args(c) }
73
- else
74
- args[0].commands.map { |c| Contrib::Redis::Quantize.get_verb(c) }
75
- end
76
- end
77
-
78
43
  def datadog_configuration
79
44
  Datadog.configuration.tracing[:redis, options]
80
45
  end
@@ -12,7 +12,7 @@ module Datadog
12
12
  # Tags handles generic common tags assignment.
13
13
  module Tags
14
14
  class << self
15
- def set_common_tags(client, span, show_command_args)
15
+ def set_common_tags(client, span, raw_command)
16
16
  if datadog_configuration[:peer_service]
17
17
  span.set_tag(
18
18
  Tracing::Metadata::Ext::TAG_PEER_SERVICE,
@@ -42,7 +42,7 @@ module Datadog
42
42
 
43
43
  span.set_tag Ext::TAG_DATABASE_INDEX, client.db.to_s
44
44
  span.set_tag Ext::TAG_DB, client.db
45
- span.set_tag Ext::TAG_RAW_COMMAND, span.resource if show_command_args
45
+ span.set_tag Ext::TAG_RAW_COMMAND, raw_command
46
46
 
47
47
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
48
48
  end
@@ -9,55 +9,68 @@ module Datadog
9
9
  module Redis
10
10
  # Instrumentation for Redis 5+
11
11
  module TraceMiddleware
12
- def call(commands, redis_config)
13
- Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
14
- datadog_configuration = resolve(redis_config)
15
- resource = get_command(commands, datadog_configuration[:command_args])
12
+ # Instruments {RedisClient::ConnectionMixin#call}.
13
+ def call(command, redis_config)
14
+ config = resolve(redis_config)
15
+ TraceMiddleware.call(redis_config, command, config[:service_name], config[:command_args]) { super }
16
+ end
17
+
18
+ # Instruments {RedisClient::ConnectionMixin#call_pipelined}.
19
+ def call_pipelined(commands, redis_config)
20
+ config = resolve(redis_config)
21
+ TraceMiddleware.call_pipelined(redis_config, commands, config[:service_name], config[:command_args]) { super }
22
+ end
16
23
 
17
- span.service = datadog_configuration[:service_name]
18
- span.span_type = Contrib::Redis::Ext::TYPE
19
- span.resource = resource
24
+ class << self
25
+ def call(client, command, service_name, command_args)
26
+ Tracing.trace(Redis::Ext::SPAN_COMMAND, type: Redis::Ext::TYPE, service: service_name) do |span|
27
+ raw_command = get_command(command, true)
28
+ span.resource = command_args ? raw_command : get_command(command, false)
20
29
 
21
- Contrib::Redis::Tags.set_common_tags(redis_config, span, datadog_configuration[:command_args])
30
+ Contrib::Redis::Tags.set_common_tags(client, span, raw_command)
22
31
 
23
- super
32
+ yield
33
+ end
24
34
  end
25
- end
26
35
 
27
- def call_pipelined(commands, redis_config)
28
- Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
29
- datadog_configuration = resolve(redis_config)
30
- pipelined_commands = get_pipeline_commands(commands, datadog_configuration[:command_args])
36
+ def call_pipelined(client, commands, service_name, command_args)
37
+ Tracing.trace(Redis::Ext::SPAN_COMMAND, type: Redis::Ext::TYPE, service: service_name) do |span|
38
+ raw_command = get_pipeline_commands(commands, true)
39
+ span.resource = command_args ? raw_command : get_pipeline_commands(commands, false)
31
40
 
32
- span.service = datadog_configuration[:service_name]
33
- span.span_type = Contrib::Redis::Ext::TYPE
34
- span.resource = pipelined_commands.join("\n")
35
- span.set_metric Contrib::Redis::Ext::METRIC_PIPELINE_LEN, pipelined_commands.length
41
+ span.set_metric Contrib::Redis::Ext::METRIC_PIPELINE_LEN, commands.length
36
42
 
37
- Contrib::Redis::Tags.set_common_tags(redis_config, span, datadog_configuration[:command_args])
43
+ Contrib::Redis::Tags.set_common_tags(client, span, raw_command)
38
44
 
39
- super
45
+ yield
46
+ end
40
47
  end
41
- end
42
48
 
43
- private
49
+ private
44
50
 
45
- def get_command(commands, boolean)
46
- if boolean
47
- Contrib::Redis::Quantize.format_command_args(commands)
48
- else
49
- Contrib::Redis::Quantize.get_verb(commands)
51
+ # Quantizes a single Redis command
52
+ def get_command(command, command_args)
53
+ if command_args
54
+ Contrib::Redis::Quantize.format_command_args(command)
55
+ else
56
+ Contrib::Redis::Quantize.get_verb(command)
57
+ end
50
58
  end
51
- end
52
59
 
53
- def get_pipeline_commands(commands, boolean)
54
- if boolean
55
- commands.map { |c| Contrib::Redis::Quantize.format_command_args(c) }
56
- else
57
- commands.map { |c| Contrib::Redis::Quantize.get_verb(c) }
60
+ # Quantizes a multi-command Redis pipeline execution
61
+ def get_pipeline_commands(commands, command_args)
62
+ list = if command_args
63
+ commands.map { |c| Contrib::Redis::Quantize.format_command_args(c) }
64
+ else
65
+ commands.map { |c| Contrib::Redis::Quantize.get_verb(c) }
66
+ end
67
+
68
+ list.empty? ? '(none)' : list.join("\n")
58
69
  end
59
70
  end
60
71
 
72
+ private
73
+
61
74
  def resolve(redis_config)
62
75
  custom = redis_config.custom[:datadog] || {}
63
76
 
@@ -137,6 +137,12 @@ module Datadog
137
137
  private
138
138
 
139
139
  def instrumented_integrations
140
+ # `instrumented_integrations` method is added only if tracing contrib extensions are required.
141
+ # If tracing is used in manual mode without integrations enabled this method does not exist.
142
+ # CI visibility gem datadog-ci uses Datadog::Tracer without requiring datadog/tracing/contrib folder
143
+ # nor enabling any integrations by default which causes EnvironmentCollector to fail.
144
+ return {} unless Datadog.configuration.tracing.respond_to?(:instrumented_integrations)
145
+
140
146
  Datadog.configuration.tracing.instrumented_integrations
141
147
  end
142
148
 
@@ -3,8 +3,8 @@
3
3
  module DDTrace
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 15
7
- PATCH = 0
6
+ MINOR = 16
7
+ PATCH = 2
8
8
  PRE = nil
9
9
  BUILD = nil
10
10
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.0
4
+ version: 1.16.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-09 00:00:00.000000000 Z
11
+ date: 2023-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.2.0
75
+ version: 0.3.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.2.0
82
+ version: 0.3.0
83
83
  description: |
84
84
  ddtrace is Datadog's tracing client for Ruby. It is used to trace requests
85
85
  as they flow across web servers, databases and microservices so that developers
@@ -514,6 +514,7 @@ files:
514
514
  - lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb
515
515
  - lib/datadog/tracing/contrib/concurrent_ruby/integration.rb
516
516
  - lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb
517
+ - lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb
517
518
  - lib/datadog/tracing/contrib/configurable.rb
518
519
  - lib/datadog/tracing/contrib/configuration/resolver.rb
519
520
  - lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb
@@ -889,7 +890,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
889
890
  - !ruby/object:Gem::Version
890
891
  version: 2.0.0
891
892
  requirements: []
892
- rubygems_version: 3.4.19
893
+ rubygems_version: 3.4.1
893
894
  signing_key:
894
895
  specification_version: 4
895
896
  summary: Datadog tracing code for your Ruby applications