ddtrace 1.11.0.beta1 → 1.11.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -1
  3. data/README.md +0 -1
  4. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +34 -7
  5. data/lib/datadog/appsec/component.rb +1 -1
  6. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +2 -3
  7. data/lib/datadog/core/configuration/agent_settings_resolver.rb +62 -11
  8. data/lib/datadog/core/configuration/settings.rb +5 -6
  9. data/lib/datadog/core/environment/identity.rb +56 -0
  10. data/lib/datadog/core/remote/client.rb +98 -19
  11. data/lib/datadog/core/remote/component.rb +29 -21
  12. data/lib/datadog/core/remote/configuration/content.rb +2 -0
  13. data/lib/datadog/core/remote/configuration/repository.rb +15 -1
  14. data/lib/datadog/core/remote/configuration/target.rb +5 -3
  15. data/lib/datadog/core/remote/negotiation.rb +57 -0
  16. data/lib/datadog/core/transport/http/negotiation.rb +1 -1
  17. data/lib/datadog/core/workers/async.rb +6 -2
  18. data/lib/datadog/core/workers/interval_loop.rb +5 -1
  19. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +6 -1
  20. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +4 -1
  21. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +4 -2
  22. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +2 -1
  23. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +6 -1
  24. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +4 -1
  25. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +6 -1
  26. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +4 -1
  27. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +6 -1
  28. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +5 -3
  29. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +4 -2
  30. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +6 -1
  31. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -2
  32. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +6 -1
  33. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -2
  34. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +6 -1
  35. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +5 -2
  36. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +6 -1
  37. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -2
  38. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +8 -0
  39. data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +14 -2
  40. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +9 -4
  41. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +34 -0
  42. data/lib/ddtrace/version.rb +4 -2
  43. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83276ed5293cf8971f19f7a1fb1198e01f5ff8d48d3dd440deff0ef3518939d6
4
- data.tar.gz: 12d22b6020e8830c91b2f68aed9ce03a2d201eafc4911c0a95171df6480cf754
3
+ metadata.gz: bf1177aae94a3724758e48ce461638de0a4b75956c8c1318251f2b568de28c5d
4
+ data.tar.gz: f42454cd32ff7eaf91c7beda1e6ff8a99726efddc8e01fdb4797b4f115c29df4
5
5
  SHA512:
6
- metadata.gz: 4d4f7fb37bd10399053c026ff92545c5a1d600447cb94b3b35439fb37008154687c09f1834115afe4ed5cddc55fe84b458db955fcd4dbd0140444ffdaa01f8a9
7
- data.tar.gz: 39d5ac62e456654550f70989e18dd3b122d3167aefc4a6b55ed5dc2ffd22c8f2b51c2f8261b2e4c009310acc2001be1a8f6ab6b0651850a45cc49cf0319ba6b1
6
+ metadata.gz: 5d5787eb9f073043151922af478a75affcfe8f2a9723fbe6c8e0561be6c7f95c700c91e1f4ca10401e018f1587f0289b1720d5c38e2cccdb80f7fcffd7eba0ba
7
+ data.tar.gz: 5f9d0adcfc38de9d60c51a46360ce60351228db21cabd07dc176a99f4bf77f80b0cc8f12dbe844ea3ae88f2384174158415a28de3e6adc1b6b54e56be1186665
data/CHANGELOG.md CHANGED
@@ -2,6 +2,52 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.11.0] - 2023-04-27
6
+
7
+ ### Highlights
8
+
9
+ As of ddtrace 1.11.0, these features are GA and emabled by default:
10
+
11
+ - CPU Profiling 2.0
12
+ - Remote Configuration
13
+ - Telemetry
14
+
15
+ For more details, check the release notes.
16
+
17
+ ### Added
18
+
19
+ * Add remote configuration, enabled by default ([#2674][], [#2678][], [#2686][], [#2687][], [#2688][], [#2689][], [#2696][], [#2705][], [#2731][], [#2732][], [#2733][], [#2739][], [#2756][], [#2769][], [#2771][], [#2773][], [#2789][], [#2805][], [#2794][])
20
+ * AppSec: Add response headers passing to WAF ([#2701][])
21
+ * Tracing: Distributed tracing for Sidekiq ([#2513][])
22
+ * Tracing: Add Roda integration ([#2368][])
23
+ * Profiling: Support disabling endpoint names collection in new profiler ([#2698][])
24
+ * Tracing: Support Sidekiq 7 ([#2810][])
25
+ * Core: Add support for Unix Domain Socket (UDS) configuration via `DD_TRACE_AGENT_URL` ([#2806][])
26
+ * Core: Enable Telemetry by default ([#2762][])
27
+
28
+ ### Changed
29
+
30
+ * Core: Allow `1` as true value in environment variables ([#2710][])
31
+ * Profiling: Enable CPU Profiling 2.0 by default ([#2702][])
32
+ * Tracing: Improve controller instrumentation and deprecate option `exception_controller` ([#2726][])
33
+ * Tracing: Implement Span Attribute Schema Environment Variable ([#2727][])
34
+ * Tracing: Change default `service_name` values (gated by feature flag) ([#2760][])
35
+
36
+ ### Fixed
37
+
38
+ * Bug: Tracing: Fix w3c propagation special character handling ([#2720][])
39
+ * Performance: Tracing: Use `+@` instead of `dup` for duplicating strings ([#2704][])
40
+ * Profiling: Avoid triggering allocation sampling during sampling ([#2690][])
41
+ * Integrations: Tracing: Fix Rails < 3 conditional check in Utils#railtie_supported? ([#2695][])
42
+ * Profiling: Do not auto-enable new profiler when rugged gem is detected ([#2741][])
43
+ * Tracing: Fix using SemanticLogger#log(severity, message, progname) ([#2748][]) ([@rqz13][])
44
+ * Profiling: Improve detection of mysql2 gem incompatibilities with profiler ([#2770][])
45
+ * AppSec: Remove check for `::Rack::Request.instance_methods.include?(:each_header)` at load time ([#2778][])
46
+ * Tracing: Fix quadratic backtracking on invalid URI ([#2788][])
47
+ * Community: Correctly set mutex ([#2757][]) ([@ixti][])
48
+
49
+ Read the [full changeset](https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...v1.11.0.beta1) and the release [milestone](https://github.com/DataDog/dd-trace-rb/milestone/121?closed=1).
50
+
5
51
  ## [1.11.0.beta1] - 2023-04-14
6
52
 
7
53
  As of ddtrace 1.11.0.beta1, CPU Profiling 2.0 is now GA and enabled by default. For more details, check the release notes.
@@ -2356,7 +2402,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
2356
2402
 
2357
2403
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2358
2404
 
2359
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.11.0.beta1...master
2405
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.11.0...master
2406
+ [1.11.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...v1.11.0
2360
2407
  [1.11.0.beta1]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...v1.11.0.beta1
2361
2408
  [1.10.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.0...v1.10.1
2362
2409
  [1.10.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.9.0...v1.10.0
@@ -3396,6 +3443,9 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3396
3443
  [#2741]: https://github.com/DataDog/dd-trace-rb/issues/2741
3397
3444
  [#2748]: https://github.com/DataDog/dd-trace-rb/issues/2748
3398
3445
  [#2756]: https://github.com/DataDog/dd-trace-rb/issues/2756
3446
+ [#2757]: https://github.com/DataDog/dd-trace-rb/issues/2757
3447
+ [#2760]: https://github.com/DataDog/dd-trace-rb/issues/2760
3448
+ [#2762]: https://github.com/DataDog/dd-trace-rb/issues/2762
3399
3449
  [#2769]: https://github.com/DataDog/dd-trace-rb/issues/2769
3400
3450
  [#2770]: https://github.com/DataDog/dd-trace-rb/issues/2770
3401
3451
  [#2771]: https://github.com/DataDog/dd-trace-rb/issues/2771
@@ -3403,6 +3453,10 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3403
3453
  [#2778]: https://github.com/DataDog/dd-trace-rb/issues/2778
3404
3454
  [#2788]: https://github.com/DataDog/dd-trace-rb/issues/2788
3405
3455
  [#2789]: https://github.com/DataDog/dd-trace-rb/issues/2789
3456
+ [#2794]: https://github.com/DataDog/dd-trace-rb/issues/2794
3457
+ [#2805]: https://github.com/DataDog/dd-trace-rb/issues/2805
3458
+ [#2806]: https://github.com/DataDog/dd-trace-rb/issues/2806
3459
+ [#2810]: https://github.com/DataDog/dd-trace-rb/issues/2810
3406
3460
  [@AdrianLC]: https://github.com/AdrianLC
3407
3461
  [@Azure7111]: https://github.com/Azure7111
3408
3462
  [@BabyGroot]: https://github.com/BabyGroot
@@ -3481,6 +3535,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3481
3535
  [@hs-bguven]: https://github.com/hs-bguven
3482
3536
  [@illdelph]: https://github.com/illdelph
3483
3537
  [@ioquatix]: https://github.com/ioquatix
3538
+ [@ixti]: https://github.com/ixti
3484
3539
  [@jamiehodge]: https://github.com/jamiehodge
3485
3540
  [@janz93]: https://github.com/janz93
3486
3541
  [@jeffjo]: https://github.com/jeffjo
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Datadog Trace Client
2
2
 
3
3
  [![Gem](https://img.shields.io/gem/v/ddtrace)](https://rubygems.org/gems/ddtrace/)
4
- [![CircleCI](https://circleci.com/gh/DataDog/dd-trace-rb/tree/master.svg?style=svg&circle-token=b0bd5ef866ec7f7b018f48731bb495f2d1372cc1)](https://circleci.com/gh/DataDog/dd-trace-rb/tree/master)
5
4
  [![codecov](https://codecov.io/gh/DataDog/dd-trace-rb/branch/master/graph/badge.svg)](https://app.codecov.io/gh/DataDog/dd-trace-rb/branch/master)
6
5
  [![YARD documentation](https://img.shields.io/badge/YARD-documentation-blue)][api docs]
7
6
 
@@ -118,6 +118,19 @@ struct cpu_and_wall_time_worker_state {
118
118
  unsigned int signal_handler_wrong_thread;
119
119
  // How many times we actually sampled (except GC samples)
120
120
  unsigned int sampled;
121
+ // How many times we skipped a sample because of the dynamic sampling rate mechanism
122
+ unsigned int skipped_sample_because_of_dynamic_sampling_rate;
123
+
124
+ // Stats for the results of calling rb_postponed_job_register_one
125
+ // The same function was already waiting to be executed
126
+ unsigned int postponed_job_skipped_already_existed;
127
+ // The function was added to the queue successfully
128
+ unsigned int postponed_job_success;
129
+ // The queue was full
130
+ unsigned int postponed_job_full;
131
+ // The function returned an unknown result code
132
+ unsigned int postponed_job_unknown_result;
133
+
121
134
  // Min/max/total wall-time spent sampling (except GC samples)
122
135
  uint64_t sampling_time_ns_min;
123
136
  uint64_t sampling_time_ns_max;
@@ -438,8 +451,20 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
438
451
 
439
452
  // Note: If we ever want to get rid of rb_postponed_job_register_one, remember not to clobber Ruby exceptions, as
440
453
  // this function does this helpful job for us now -- https://github.com/ruby/ruby/commit/a98e343d39c4d7bf1e2190b076720f32d9f298b3.
441
- /*int result =*/ rb_postponed_job_register_one(0, sample_from_postponed_job, NULL);
442
- // TODO: Do something with result (potentially update tracking counters?)
454
+ int result = rb_postponed_job_register_one(0, sample_from_postponed_job, NULL);
455
+
456
+ // Officially, the result of rb_postponed_job_register_one is documented as being opaque, but in practice it does not
457
+ // seem to have changed between Ruby 2.3 and 3.2, and so we track it as a debugging mechanism
458
+ switch (result) {
459
+ case 0:
460
+ state->stats.postponed_job_full++; break;
461
+ case 1:
462
+ state->stats.postponed_job_success++; break;
463
+ case 2:
464
+ state->stats.postponed_job_skipped_already_existed++; break;
465
+ default:
466
+ state->stats.postponed_job_unknown_result++;
467
+ }
443
468
  }
444
469
 
445
470
  // The actual sampling trigger loop always runs **without** the global vm lock.
@@ -451,9 +476,6 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
451
476
  while (atomic_load(&state->should_run)) {
452
477
  state->stats.trigger_sample_attempts++;
453
478
 
454
- // TODO: This is still a placeholder for a more complex mechanism. In particular:
455
- // * We want to do more than having a fixed sampling rate
456
-
457
479
  current_gvl_owner owner = gvl_owner();
458
480
  if (owner.valid) {
459
481
  // Note that reading the GVL owner and sending them a signal is a race -- the Ruby VM keeps on executing while
@@ -519,8 +541,8 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
519
541
 
520
542
  long wall_time_ns_before_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
521
543
 
522
- if (!dynamic_sampling_rate_should_sample(&state->dynamic_sampling_rate, wall_time_ns_before_sample)) {
523
- // TODO: Add a counter for this
544
+ if (state->dynamic_sampling_rate_enabled && !dynamic_sampling_rate_should_sample(&state->dynamic_sampling_rate, wall_time_ns_before_sample)) {
545
+ state->stats.skipped_sample_because_of_dynamic_sampling_rate++;
524
546
  return Qnil;
525
547
  }
526
548
 
@@ -777,6 +799,11 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
777
799
  ID2SYM(rb_intern("signal_handler_enqueued_sample")), /* => */ UINT2NUM(state->stats.signal_handler_enqueued_sample),
778
800
  ID2SYM(rb_intern("signal_handler_wrong_thread")), /* => */ UINT2NUM(state->stats.signal_handler_wrong_thread),
779
801
  ID2SYM(rb_intern("sampled")), /* => */ UINT2NUM(state->stats.sampled),
802
+ ID2SYM(rb_intern("skipped_sample_because_of_dynamic_sampling_rate")), /* => */ UINT2NUM(state->stats.skipped_sample_because_of_dynamic_sampling_rate),
803
+ ID2SYM(rb_intern("postponed_job_skipped_already_existed")), /* => */ UINT2NUM(state->stats.postponed_job_skipped_already_existed),
804
+ ID2SYM(rb_intern("postponed_job_success")), /* => */ UINT2NUM(state->stats.postponed_job_success),
805
+ ID2SYM(rb_intern("postponed_job_full")), /* => */ UINT2NUM(state->stats.postponed_job_full),
806
+ ID2SYM(rb_intern("postponed_job_unknown_result")), /* => */ UINT2NUM(state->stats.postponed_job_unknown_result),
780
807
  ID2SYM(rb_intern("sampling_time_ns_min")), /* => */ pretty_sampling_time_ns_min,
781
808
  ID2SYM(rb_intern("sampling_time_ns_max")), /* => */ pretty_sampling_time_ns_max,
782
809
  ID2SYM(rb_intern("sampling_time_ns_total")), /* => */ pretty_sampling_time_ns_total,
@@ -53,7 +53,7 @@ module Datadog
53
53
  if new && new.ready?
54
54
  old = @processor
55
55
  @processor = new
56
- old.finalize
56
+ old.finalize if old
57
57
  end
58
58
  end
59
59
  end
@@ -23,12 +23,11 @@ module Datadog
23
23
  @oneshot_tags_sent = false
24
24
  end
25
25
 
26
- # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
26
+ # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
27
27
  def call(env)
28
28
  return @app.call(env) unless Datadog::AppSec.enabled?
29
29
 
30
30
  Datadog::Core::Remote.active_remote.barrier(:once) unless Datadog::Core::Remote.active_remote.nil?
31
- processor = Datadog::AppSec.processor
32
31
 
33
32
  processor = nil
34
33
  ready = false
@@ -89,7 +88,7 @@ module Datadog
89
88
  processor.deactivate_context
90
89
  end
91
90
  end
92
- # rubocop:enable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
91
+ # rubocop:enable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
93
92
 
94
93
  private
95
94
 
@@ -95,9 +95,7 @@ module Datadog
95
95
  end
96
96
 
97
97
  def adapter
98
- # If no agent settings have been provided, we try to connect using a local unix socket.
99
- # We only do so if the socket is present when `ddtrace` runs.
100
- if should_use_uds_fallback?
98
+ if should_use_uds? && !mixed_http_and_uds?
101
99
  Datadog::Transport::Ext::UnixSocket::ADAPTER
102
100
  else
103
101
  Datadog::Transport::Ext::HTTP::ADAPTER
@@ -118,7 +116,7 @@ module Datadog
118
116
  ),
119
117
  DetectedConfiguration.new(
120
118
  friendly_name: "#{Datadog::Tracing::Configuration::Ext::Transport::ENV_DEFAULT_URL} environment variable",
121
- value: parsed_url && parsed_url.hostname
119
+ value: parsed_http_url && parsed_http_url.hostname
122
120
  ),
123
121
  DetectedConfiguration.new(
124
122
  friendly_name: "#{Datadog::Core::Configuration::Ext::Transport::ENV_DEFAULT_HOST} environment variable",
@@ -141,7 +139,7 @@ module Datadog
141
139
  ),
142
140
  DetectedConfiguration.new(
143
141
  friendly_name: "#{Datadog::Tracing::Configuration::Ext::Transport::ENV_DEFAULT_URL} environment variable",
144
- value: parsed_url && parsed_url.port,
142
+ value: parsed_http_url && parsed_http_url.port,
145
143
  ),
146
144
  try_parsing_as_integer(
147
145
  friendly_name: "#{Datadog::Tracing::Configuration::Ext::Transport::ENV_DEFAULT_PORT} environment variable",
@@ -169,16 +167,29 @@ module Datadog
169
167
  end
170
168
 
171
169
  def hostname
172
- configured_hostname || (should_use_uds_fallback? ? nil : Datadog::Transport::Ext::HTTP::DEFAULT_HOST)
170
+ configured_hostname || (should_use_uds? ? nil : Datadog::Transport::Ext::HTTP::DEFAULT_HOST)
173
171
  end
174
172
 
175
173
  def port
176
- configured_port || (should_use_uds_fallback? ? nil : Datadog::Transport::Ext::HTTP::DEFAULT_PORT)
174
+ configured_port || (should_use_uds? ? nil : Datadog::Transport::Ext::HTTP::DEFAULT_PORT)
177
175
  end
178
176
 
179
177
  # Unix socket path in the file system
180
178
  def uds_path
181
- uds_fallback
179
+ if mixed_http_and_uds?
180
+ nil
181
+ elsif parsed_url && unix_scheme?(parsed_url)
182
+ path = parsed_url.to_s
183
+ # Some versions of the built-in uri gem leave the original url untouched, and others remove the //, so this
184
+ # supports both
185
+ if path.start_with?('unix://')
186
+ path.sub('unix://', '')
187
+ else
188
+ path.sub('unix:', '')
189
+ end
190
+ else
191
+ uds_fallback
192
+ end
182
193
  end
183
194
 
184
195
  # Defaults to +nil+, letting the adapter choose what default
@@ -210,8 +221,11 @@ module Datadog
210
221
  end
211
222
  end
212
223
 
213
- def should_use_uds_fallback?
214
- uds_fallback != nil
224
+ def should_use_uds?
225
+ parsed_url && unix_scheme?(parsed_url) ||
226
+ # If no agent settings have been provided, we try to connect using a local unix socket.
227
+ # We only do so if the socket is present when `ddtrace` runs.
228
+ !uds_fallback.nil?
215
229
  end
216
230
 
217
231
  def parsed_url
@@ -223,7 +237,7 @@ module Datadog
223
237
  if unparsed_url_from_env
224
238
  parsed = URI.parse(unparsed_url_from_env)
225
239
 
226
- if %w[http https].include?(parsed.scheme)
240
+ if http_scheme?(parsed) || unix_scheme?(parsed)
227
241
  parsed
228
242
  else
229
243
  # rubocop:disable Layout/LineLength
@@ -266,6 +280,43 @@ module Datadog
266
280
  logger.warn(message) if logger
267
281
  end
268
282
 
283
+ def http_scheme?(uri)
284
+ ['http', 'https'].include?(uri.scheme)
285
+ end
286
+
287
+ # Expected to return nil (not false!) when it's not http
288
+ def parsed_http_url
289
+ parsed_url if parsed_url && http_scheme?(parsed_url)
290
+ end
291
+
292
+ def unix_scheme?(uri)
293
+ uri.scheme == 'unix'
294
+ end
295
+
296
+ # When we have mixed settings for http/https and uds, we print a warning and ignore the uds settings
297
+ def mixed_http_and_uds?
298
+ return @mixed_http_and_uds if defined?(@mixed_http_and_uds)
299
+
300
+ @mixed_http_and_uds = (configured_hostname || configured_port) && should_use_uds?
301
+
302
+ if @mixed_http_and_uds
303
+ warn_if_configuration_mismatch(
304
+ [
305
+ DetectedConfiguration.new(
306
+ friendly_name: 'configuration of hostname/port for http/https use',
307
+ value: "hostname: '#{configured_hostname}', port: #{configured_port.inspect}",
308
+ ),
309
+ DetectedConfiguration.new(
310
+ friendly_name: 'configuration for unix domain socket',
311
+ value: "unix://#{uds_path}",
312
+ ),
313
+ ]
314
+ )
315
+ end
316
+
317
+ @mixed_http_and_uds
318
+ end
319
+
269
320
  # The settings.tracing.transport_options allows users to have full control over the settings used to
270
321
  # communicate with the agent. In the general case, we can't extract the configuration from this proc, but
271
322
  # in the specific case of the http and unix socket adapters we can, and we use this method together with the
@@ -468,11 +468,11 @@ module Datadog
468
468
  settings :telemetry do
469
469
  # Enable telemetry collection. This allows telemetry events to be emitted to the telemetry API.
470
470
  #
471
- # @default `DD_INSTRUMENTATION_TELEMETRY_ENABLED` environment variable, otherwise `false`. In a future release,
472
- # this value will be changed to `true` by default as documented [here](https://docs.datadoghq.com/tracing/configure_data_security/#telemetry-collection).
471
+ # @default `DD_INSTRUMENTATION_TELEMETRY_ENABLED` environment variable, otherwise `true`.
472
+ # Can be disabled as documented [here](https://docs.datadoghq.com/tracing/configure_data_security/#telemetry-collection).
473
473
  # @return [Boolean]
474
474
  option :enabled do |o|
475
- o.default { env_to_bool(Core::Telemetry::Ext::ENV_ENABLED, false) }
475
+ o.default { env_to_bool(Core::Telemetry::Ext::ENV_ENABLED, true) }
476
476
  o.lazy
477
477
  end
478
478
  end
@@ -482,11 +482,10 @@ module Datadog
482
482
  settings :remote do
483
483
  # Enable remote configuration. This allows fetching of remote configuration for live updates.
484
484
  #
485
- # @default `DD_REMOTE_CONFIGURATION_ENABLED` environment variable, otherwise `false`. In a future release,
486
- # this value will be changed to `true` by default.
485
+ # @default `DD_REMOTE_CONFIGURATION_ENABLED` environment variable, otherwise `true`.
487
486
  # @return [Boolean]
488
487
  option :enabled do |o|
489
- o.default { env_to_bool(Core::Remote::Ext::ENV_ENABLED, false) }
488
+ o.default { env_to_bool(Core::Remote::Ext::ENV_ENABLED, true) }
490
489
  o.lazy
491
490
  end
492
491
 
@@ -49,9 +49,65 @@ module Datadog
49
49
  Core::Environment::Ext::LANG_VERSION
50
50
  end
51
51
 
52
+ # Returns tracer version, rubygems-style
52
53
  def tracer_version
53
54
  Core::Environment::Ext::TRACER_VERSION
54
55
  end
56
+
57
+ # Returns tracer version, comforming to https://semver.org/spec/v2.0.0.html
58
+ def tracer_version_semver2
59
+ # from ddtrace/version.rb, we have MAJOR.MINOR.PATCH plus optional .PRE and .BUILD
60
+ # - transform .PRE to -PRE if present
61
+ # - transform .BUILD to +BUILD if present
62
+ # - keep triplet segments before that
63
+
64
+ m = SEMVER2_RE.match(tracer_version)
65
+
66
+ pre = "-#{m[:pre]}" if m[:pre]
67
+ build = "+gha#{m[:gha_run_id]}.g#{m[:git_sha]}.#{m[:branch].tr('.', '-')}" if m[:build]
68
+
69
+ "#{m[:major]}.#{m[:minor]}.#{m[:patch]}#{pre}#{build}"
70
+ end
71
+
72
+ SEMVER2_RE = /
73
+ ^
74
+ # mandatory segments
75
+ (?<major>\d+)
76
+ \.
77
+ (?<minor>\d+)
78
+ \.
79
+ (?<patch>\d+)
80
+
81
+ # pre segments start with a value
82
+ # - containing at least one alpha
83
+ # - that is not part of our build segments expected values
84
+ # and stop with a value that is not part of our build segments expected values
85
+ (?:
86
+ \.
87
+ (?<pre>
88
+ (?!gha)
89
+ [a-zA-Z0-9]*[a-zA-Z][a-zA-Z0-9]*
90
+ (?:
91
+ \.
92
+ (?!gha)
93
+ [a-zA-Z0-9]+
94
+ )*
95
+ )
96
+ )?
97
+
98
+ # build segments: ours include CI info (`gha`), then git (`g`), then branch name
99
+ (?:
100
+ \.
101
+ (?<build>
102
+ gha(?<gha_run_id>\d+)
103
+ \.
104
+ g(?<git_sha>[a-f0-9]+)
105
+ \.
106
+ (?<branch>(?:[a-zA-Z0-9.])+)
107
+ )
108
+ )?
109
+ $
110
+ /xm.freeze
55
111
  end
56
112
  end
57
113
  end
@@ -27,7 +27,7 @@ module Datadog
27
27
  end
28
28
  end
29
29
 
30
- # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity
30
+ # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/MethodLength,Metrics/CyclomaticComplexity
31
31
  def sync
32
32
  # TODO: Skip sync if no capabilities are registered
33
33
  response = transport.send_config(payload)
@@ -40,13 +40,20 @@ module Datadog
40
40
  return
41
41
  end
42
42
 
43
- paths = response.client_configs.map do |path|
44
- Configuration::Path.parse(path)
45
- end
43
+ begin
44
+ paths = response.client_configs.map do |path|
45
+ Configuration::Path.parse(path)
46
+ end
46
47
 
47
- targets = Configuration::TargetMap.parse(response.targets)
48
+ targets = Configuration::TargetMap.parse(response.targets)
48
49
 
49
- contents = Configuration::ContentList.parse(response.target_files)
50
+ contents = Configuration::ContentList.parse(response.target_files)
51
+ rescue Remote::Configuration::Path::ParseError => e
52
+ raise SyncError, e.message
53
+ end
54
+
55
+ # To make sure steep does not complain
56
+ return unless paths && targets && contents
50
57
 
51
58
  # TODO: sometimes it can strangely be so that paths.empty?
52
59
  # TODO: sometimes it can strangely be so that targets.empty?
@@ -100,17 +107,44 @@ module Datadog
100
107
  else
101
108
  dispatcher.dispatch(changes, repository)
102
109
  end
103
- else
104
- raise SyncError, "unexpected transport response: #{response.inspect}"
105
110
  end
106
111
  end
107
- # rubocop:enable Metrics/AbcSize,Metrics/PerceivedComplexity
112
+ # rubocop:enable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/MethodLength,Metrics/CyclomaticComplexity
108
113
 
109
114
  private
110
115
 
111
- def payload
116
+ def payload # rubocop:disable Metrics/MethodLength
112
117
  state = repository.state
113
118
 
119
+ client_tracer_tags = [
120
+ "platform:#{native_platform}", # native platform
121
+ # "asm.config.rules:#{}", # TODO: defined|undefined
122
+ # "asm.config.enabled:#{}", # TODO: true|false|undefined
123
+ "ruby.tracer.version:#{Core::Environment::Identity.tracer_version}",
124
+ "ruby.runtime.platform:#{RUBY_PLATFORM}",
125
+ "ruby.runtime.version:#{RUBY_VERSION}",
126
+ "ruby.runtime.engine.name:#{RUBY_ENGINE}",
127
+ "ruby.runtime.engine.version:#{ruby_engine_version}",
128
+ "ruby.rubygems.platform.local:#{Gem::Platform.local}",
129
+ "ruby.gem.libddwaf.version:#{gem_spec('libddwaf').version}",
130
+ "ruby.gem.libddwaf.platform:#{gem_spec('libddwaf').platform}",
131
+ "ruby.gem.libdatadog.version:#{gem_spec('libdatadog').version}",
132
+ "ruby.gem.libdatadog.platform:#{gem_spec('libdatadog').platform}",
133
+ ]
134
+
135
+ client_tracer = {
136
+ runtime_id: Core::Environment::Identity.id,
137
+ language: Core::Environment::Identity.lang,
138
+ tracer_version: tracer_version_semver2,
139
+ service: Datadog.configuration.service,
140
+ env: Datadog.configuration.env,
141
+ tags: client_tracer_tags,
142
+ }
143
+
144
+ app_version = Datadog.configuration.version
145
+
146
+ client_tracer[:app_version] = app_version if app_version
147
+
114
148
  {
115
149
  client: {
116
150
  state: {
@@ -125,21 +159,66 @@ module Datadog
125
159
  products: @capabilities.products,
126
160
  is_tracer: true,
127
161
  is_agent: false,
128
- client_tracer: {
129
- runtime_id: Core::Environment::Identity.id,
130
- language: Core::Environment::Identity.lang,
131
- tracer_version: Core::Environment::Identity.tracer_version,
132
- service: Datadog.configuration.service,
133
- env: Datadog.configuration.env,
134
- # app_version: app_version, # TODO: I don't know what this is
135
- tags: [], # TODO: add nice tags!
136
- },
162
+ client_tracer: client_tracer,
137
163
  # base64 is needed otherwise the Go agent fails with an unmarshal error
138
164
  capabilities: @capabilities.base64_capabilities
139
165
  },
140
166
  cached_target_files: state.cached_target_files,
141
167
  }
142
168
  end
169
+
170
+ def tracer_version_semver2
171
+ @tracer_version_semver2 ||= Core::Environment::Identity.tracer_version_semver2
172
+ end
173
+
174
+ def ruby_engine_version
175
+ @ruby_engine_version ||= defined?(RUBY_ENGINE_VERSION) ? RUBY_ENGINE_VERSION : RUBY_VERSION
176
+ end
177
+
178
+ def gem_spec(name)
179
+ (@gem_specs ||= {})[name] ||= ::Gem.loaded_specs[name] || GemSpecificationFallback.new(nil, nil)
180
+ end
181
+
182
+ def native_platform
183
+ return @native_platform unless @native_platform.nil?
184
+
185
+ os = if RUBY_ENGINE == 'jruby'
186
+ os_name = java.lang.System.get_property('os.name')
187
+
188
+ case os_name
189
+ when /linux/i then 'linux'
190
+ when /mac/i then 'darwin'
191
+ else os_name
192
+ end
193
+ else
194
+ Gem::Platform.local.os
195
+ end
196
+
197
+ version = if os != 'linux'
198
+ nil
199
+ elsif RUBY_PLATFORM =~ /linux-(.+)$/
200
+ # Old rubygems don't handle non-gnu linux correctly
201
+ Regexp.last_match(1)
202
+ else
203
+ 'gnu'
204
+ end
205
+
206
+ cpu = if RUBY_ENGINE == 'jruby'
207
+ os_arch = java.lang.System.get_property('os.arch')
208
+
209
+ case os_arch
210
+ when 'amd64' then 'x86_64'
211
+ when 'aarch64' then os == 'darwin' ? 'arm64' : 'aarch64'
212
+ else os_arch
213
+ end
214
+ else
215
+ Gem::Platform.local.cpu
216
+ end
217
+
218
+ @native_platform = [cpu, os, version].compact.join('-')
219
+ end
220
+
221
+ GemSpecificationFallback = _ = Struct.new(:version, :platform) # rubocop:disable Naming/ConstantName
143
222
  end
144
223
  end
145
224
  end