ddtrace 1.4.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -2
  3. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +0 -2
  4. data/lib/datadog/appsec/configuration/settings.rb +0 -2
  5. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +0 -2
  6. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  7. data/lib/datadog/ci/ext/environment.rb +16 -4
  8. data/lib/datadog/core/configuration/agent_settings_resolver.rb +0 -3
  9. data/lib/datadog/core/configuration/components.rb +8 -2
  10. data/lib/datadog/core/configuration/settings.rb +69 -2
  11. data/lib/datadog/core/configuration.rb +1 -1
  12. data/lib/datadog/core/header_collection.rb +41 -0
  13. data/lib/datadog/core/telemetry/collector.rb +0 -2
  14. data/lib/datadog/core/workers/async.rb +0 -2
  15. data/lib/datadog/profiling/collectors/old_stack.rb +1 -1
  16. data/lib/datadog/profiling.rb +1 -1
  17. data/lib/datadog/tracing/client_ip.rb +153 -0
  18. data/lib/datadog/tracing/configuration/ext.rb +12 -0
  19. data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
  20. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +0 -2
  21. data/lib/datadog/tracing/contrib/ext.rb +19 -0
  22. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -2
  23. data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -2
  24. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -1
  25. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -4
  26. data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
  27. data/lib/datadog/tracing/contrib/rack/middlewares.rb +92 -38
  28. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +83 -9
  29. data/lib/datadog/tracing/flush.rb +57 -35
  30. data/lib/datadog/tracing/metadata/ext.rb +3 -9
  31. data/lib/datadog/tracing/metadata/tagging.rb +9 -0
  32. data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -0
  33. data/lib/datadog/tracing/sampling/rate_sampler.rb +10 -0
  34. data/lib/datadog/tracing/sampling/span/ext.rb +29 -0
  35. data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
  36. data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
  37. data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
  38. data/lib/datadog/tracing/sampling/span/sampler.rb +64 -0
  39. data/lib/datadog/tracing/span_operation.rb +0 -2
  40. data/lib/datadog/tracing/trace_operation.rb +22 -3
  41. data/lib/datadog/tracing/trace_segment.rb +1 -2
  42. data/lib/datadog/tracing/tracer.rb +31 -5
  43. data/lib/ddtrace/version.rb +2 -2
  44. metadata +19 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e708799bd5320bcc45e0cd79d9893ef278ea1b30205058cae88ed9409371bd56
4
- data.tar.gz: c34df6aaebb0a8a16b68a6ccd12397b101fe5e74f450b599d9a94bb01cc272b5
3
+ metadata.gz: 480825e1e52697f2e7b49f605a733b2e53072b36aac74b664c62fada4e6acac2
4
+ data.tar.gz: 288731a19cf08d4fb6d546ef3481a6a571823de993df97d5e5b14ff4cfc3b820
5
5
  SHA512:
6
- metadata.gz: f33d2ddfb796efa2dfda6b5b02dab623e8fcfbcf263cb820a0e78d291f49dc06e587e535c7a8afe40e26c830b2b0dac7539c4302ed76aa24579560fa687ea154
7
- data.tar.gz: 7cc6918e72984329af2f5a002a131d8ef965a276b9dc4ca74e1e6bda595f8c106f535c98bc69626e4394ba0f5c6a4e5103606e9946453bbe3ef8eb5d12922e0a
6
+ metadata.gz: 902874e4c974a680373aa6c6ecf0b40a21bb285c266dd340e5d89c92827375e5e3c6480cc7988719a54eaa8e5e3829ddbb914afc84179e53d99fa1dff50759ad
7
+ data.tar.gz: 890b97da4ceda1d07358b3a019a23ce0d224410359ea30f9128050c1de3a05ce077bd4592517b0606323215a6dac9b306bde38efddf69e742c6b324f52c239e7
data/CHANGELOG.md CHANGED
@@ -2,11 +2,37 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.5.0] - 2022-09-29
6
+
7
+ ### Deprecation notice
8
+
9
+ * `c.tracing.instrument :rack, { quantize: { base: ... } }` will change its default from `:exclude` to `:show` in a future version. Voluntarily moving to `:show` is recommended.
10
+ * `c.tracing.instrument :rack, { quantize: { query: { show: ... } }` will change its default to `:all` in a future version, together with `quantize.query.obfuscate` changing to `:internal`. Voluntarily moving to these future values is recommended.
11
+
12
+ ### Added
13
+
14
+ * Feature: Single Span Sampling ([#2128][])
15
+ * Add query string automatic redaction ([#2283][])
16
+ * Use full URL in `http.url` tag ([#2265][])
17
+ * Add `http.useragent` tag ([#2252][])
18
+ * Add `http.client_ip` tag for Rack-based frameworks ([#2248][])
19
+ * Ci-app: CI: Fetch committer and author in Bitrise ([#2258][])
20
+
21
+ ### Changed
22
+
23
+ * Bump allowed version of debase-ruby_core_source to include v0.10.17 ([#2267][])
24
+
25
+ ### Fixed
26
+
27
+ * Bug: Fix `service_nam` typo to `service_name` ([#2296][])
28
+ * Bug: Check AppSec Rails for railties instead of rails meta gem ([#2293][]) ([@seuros][])
29
+ * Ci-app: Correctly extract commit message from AppVeyor ([#2257][])
30
+
5
31
  ## [1.4.2] - 2022-09-27
6
32
 
7
33
  ### Fixed
8
34
 
9
- OpenTracing context propagation (#2191, #2289)
35
+ OpenTracing context propagation ([#2191][], [#2289][])
10
36
 
11
37
  ## [1.4.1] - 2022-09-15
12
38
 
@@ -2104,6 +2130,7 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
2104
2130
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2105
2131
 
2106
2132
  [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.4.2...master
2133
+ [1.5.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.4.2...v1.5.0
2107
2134
  [1.4.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.4.1...v1.4.2
2108
2135
  [1.4.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.4.0...v1.4.1
2109
2136
  [1.4.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.3.0...v1.4.0
@@ -2973,6 +3000,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2973
3000
  [#2113]: https://github.com/DataDog/dd-trace-rb/issues/2113
2974
3001
  [#2118]: https://github.com/DataDog/dd-trace-rb/issues/2118
2975
3002
  [#2125]: https://github.com/DataDog/dd-trace-rb/issues/2125
3003
+ [#2128]: https://github.com/DataDog/dd-trace-rb/issues/2128
2976
3004
  [#2134]: https://github.com/DataDog/dd-trace-rb/issues/2134
2977
3005
  [#2138]: https://github.com/DataDog/dd-trace-rb/issues/2138
2978
3006
  [#2140]: https://github.com/DataDog/dd-trace-rb/issues/2140
@@ -2985,12 +3013,23 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2985
3013
  [#2173]: https://github.com/DataDog/dd-trace-rb/issues/2173
2986
3014
  [#2174]: https://github.com/DataDog/dd-trace-rb/issues/2174
2987
3015
  [#2180]: https://github.com/DataDog/dd-trace-rb/issues/2180
3016
+ [#2191]: https://github.com/DataDog/dd-trace-rb/issues/2191
2988
3017
  [#2200]: https://github.com/DataDog/dd-trace-rb/issues/2200
2989
3018
  [#2201]: https://github.com/DataDog/dd-trace-rb/issues/2201
2990
3019
  [#2219]: https://github.com/DataDog/dd-trace-rb/issues/2219
2991
3020
  [#2229]: https://github.com/DataDog/dd-trace-rb/issues/2229
3021
+ [#2248]: https://github.com/DataDog/dd-trace-rb/issues/2248
2992
3022
  [#2250]: https://github.com/DataDog/dd-trace-rb/issues/2250
3023
+ [#2252]: https://github.com/DataDog/dd-trace-rb/issues/2252
3024
+ [#2257]: https://github.com/DataDog/dd-trace-rb/issues/2257
3025
+ [#2258]: https://github.com/DataDog/dd-trace-rb/issues/2258
3026
+ [#2265]: https://github.com/DataDog/dd-trace-rb/issues/2265
3027
+ [#2267]: https://github.com/DataDog/dd-trace-rb/issues/2267
2993
3028
  [#2279]: https://github.com/DataDog/dd-trace-rb/issues/2279
3029
+ [#2283]: https://github.com/DataDog/dd-trace-rb/issues/2283
3030
+ [#2289]: https://github.com/DataDog/dd-trace-rb/issues/2289
3031
+ [#2293]: https://github.com/DataDog/dd-trace-rb/issues/2293
3032
+ [#2296]: https://github.com/DataDog/dd-trace-rb/issues/2296
2994
3033
  [@AdrianLC]: https://github.com/AdrianLC
2995
3034
  [@Azure7111]: https://github.com/Azure7111
2996
3035
  [@BabyGroot]: https://github.com/BabyGroot
@@ -3112,6 +3151,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3112
3151
  [@saturnflyer]: https://github.com/saturnflyer
3113
3152
  [@sco11morgan]: https://github.com/sco11morgan
3114
3153
  [@senny]: https://github.com/senny
3154
+ [@seuros]: https://github.com/seuros
3115
3155
  [@shayonj]: https://github.com/shayonj
3116
3156
  [@sinsoku]: https://github.com/sinsoku
3117
3157
  [@skcc321]: https://github.com/skcc321
@@ -3132,4 +3172,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3132
3172
  [@walterking]: https://github.com/walterking
3133
3173
  [@y-yagi]: https://github.com/y-yagi
3134
3174
  [@yukimurasawa]: https://github.com/yukimurasawa
3135
- [@zachmccormick]: https://github.com/zachmccormick
3175
+ [@zachmccormick]: https://github.com/zachmccormick
@@ -68,7 +68,6 @@ module Datadog
68
68
 
69
69
  # Used to check if profiler is supported, including user-visible clear messages explaining why their
70
70
  # system may not be supported.
71
- # rubocop:disable Metrics/ModuleLength
72
71
  module Supported
73
72
  private_class_method def self.explain_issue(*reason, suggested:)
74
73
  { reason: reason, suggested: suggested }
@@ -284,7 +283,6 @@ module Datadog
284
283
  no_binaries_for_current_platform unless Libdatadog.pkgconfig_folder
285
284
  end
286
285
  end
287
- # rubocop:enable Metrics/ModuleLength
288
286
  end
289
287
  end
290
288
  end
@@ -5,7 +5,6 @@ module Datadog
5
5
  module Configuration
6
6
  # Configuration settings, acting as an integration registry
7
7
  # TODO: as with Configuration, this is a trivial implementation
8
- # rubocop:disable Metrics/ClassLength
9
8
  class Settings
10
9
  class << self
11
10
  def boolean
@@ -188,7 +187,6 @@ module Datadog
188
187
  initialize
189
188
  end
190
189
  end
191
- # rubocop:enable Metrics/ClassLength
192
190
  end
193
191
  end
194
192
  end
@@ -13,7 +13,6 @@ module Datadog
13
13
  module Rack
14
14
  module Gateway
15
15
  # Watcher for Rack gateway events
16
- # rubocop:disable Metrics/ModuleLength
17
16
  module Watcher
18
17
  # rubocop:disable Metrics/AbcSize
19
18
  # rubocop:disable Metrics/MethodLength
@@ -161,7 +160,6 @@ module Datadog
161
160
  end
162
161
  end
163
162
  end
164
- # rubocop:enable Metrics/ModuleLength
165
163
  end
166
164
  end
167
165
  end
@@ -19,7 +19,7 @@ module Datadog
19
19
  register_as :rails, auto_patch: false
20
20
 
21
21
  def self.version
22
- Gem.loaded_specs['rails'] && Gem.loaded_specs['rails'].version
22
+ Gem.loaded_specs['railties'] && Gem.loaded_specs['railties'].version
23
23
  end
24
24
 
25
25
  def self.loaded?
@@ -10,7 +10,6 @@ module Datadog
10
10
  module CI
11
11
  module Ext
12
12
  # Defines constants for CI tags
13
- # rubocop:disable Metrics/ModuleLength:
14
13
  module Environment
15
14
  include Kernel # Ensure that kernel methods are always available (https://sorbet.org/docs/error-reference#7003)
16
15
 
@@ -97,6 +96,12 @@ module Datadog
97
96
  tag = env['APPVEYOR_REPO_TAG_NAME']
98
97
  end
99
98
 
99
+ commit_message = env['APPVEYOR_REPO_COMMIT_MESSAGE']
100
+ if commit_message
101
+ extended = env['APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED']
102
+ commit_message = "#{commit_message}\n#{extended}" if extended
103
+ end
104
+
100
105
  {
101
106
  TAG_PROVIDER_NAME => 'appveyor',
102
107
  Core::Git::Ext::TAG_REPOSITORY_URL => repository,
@@ -111,7 +116,7 @@ module Datadog
111
116
  Core::Git::Ext::TAG_TAG => tag,
112
117
  Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['APPVEYOR_REPO_COMMIT_AUTHOR'],
113
118
  Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL'],
114
- Core::Git::Ext::TAG_COMMIT_MESSAGE => env['APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED']
119
+ Core::Git::Ext::TAG_COMMIT_MESSAGE => commit_message
115
120
  }
116
121
  end
117
122
 
@@ -330,6 +335,10 @@ module Datadog
330
335
  branch = (
331
336
  env['BITRISEIO_GIT_BRANCH_DEST'] || env['BITRISE_GIT_BRANCH']
332
337
  )
338
+ commiter_email = (
339
+ env['GIT_CLONE_COMMIT_COMMITER_EMAIL'] || env['GIT_CLONE_COMMIT_COMMITER_NAME']
340
+ )
341
+
333
342
  {
334
343
  TAG_PROVIDER_NAME => 'bitrise',
335
344
  TAG_PIPELINE_ID => env['BITRISE_BUILD_SLUG'],
@@ -341,7 +350,11 @@ module Datadog
341
350
  Core::Git::Ext::TAG_COMMIT_SHA => commit,
342
351
  Core::Git::Ext::TAG_BRANCH => branch,
343
352
  Core::Git::Ext::TAG_TAG => env['BITRISE_GIT_TAG'],
344
- Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BITRISE_GIT_MESSAGE']
353
+ Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BITRISE_GIT_MESSAGE'],
354
+ Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['GIT_CLONE_COMMIT_AUTHOR_NAME'],
355
+ Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['GIT_CLONE_COMMIT_AUTHOR_EMAIL'],
356
+ Core::Git::Ext::TAG_COMMIT_COMMITTER_NAME => env['GIT_CLONE_COMMIT_COMMITER_NAME'],
357
+ Core::Git::Ext::TAG_COMMIT_COMMITTER_EMAIL => commiter_email
345
358
  }
346
359
  end
347
360
 
@@ -499,7 +512,6 @@ module Datadog
499
512
  [nil, name_and_email]
500
513
  end
501
514
  end
502
- # rubocop:enable Metrics/ModuleLength:
503
515
  end
504
516
  end
505
517
  end
@@ -18,8 +18,6 @@ module Datadog
18
18
  #
19
19
  # Whenever there is a conflict (different configurations are provided in different orders), it MUST warn the users
20
20
  # about it and pick a value based on the following priority: code > environment variable > defaults.
21
- #
22
- # rubocop:disable Metrics/ClassLength
23
21
  class AgentSettingsResolver
24
22
  AgentSettings = \
25
23
  Struct.new(
@@ -359,7 +357,6 @@ module Datadog
359
357
  end
360
358
  end
361
359
  end
362
- # rubocop:enable Metrics/ClassLength
363
360
  end
364
361
  end
365
362
  end
@@ -11,12 +11,13 @@ require_relative '../workers/runtime_metrics'
11
11
  require_relative '../../tracing/tracer'
12
12
  require_relative '../../tracing/flush'
13
13
  require_relative '../../tracing/sync_writer'
14
+ require_relative '../../tracing/sampling/span/rule_parser'
15
+ require_relative '../../tracing/sampling/span/sampler'
14
16
 
15
17
  module Datadog
16
18
  module Core
17
19
  module Configuration
18
20
  # Global components for the trace library.
19
- # rubocop:disable Metrics/ClassLength
20
21
  class Components
21
22
  class << self
22
23
  def build_health_metrics(settings)
@@ -80,6 +81,7 @@ module Datadog
80
81
  enabled: settings.tracing.enabled,
81
82
  trace_flush: trace_flush,
82
83
  sampler: sampler,
84
+ span_sampler: build_span_sampler(settings),
83
85
  writer: writer,
84
86
  tags: build_tracer_tags(settings),
85
87
  )
@@ -183,6 +185,11 @@ module Datadog
183
185
  end
184
186
  end
185
187
 
188
+ def build_span_sampler(settings)
189
+ rules = Tracing::Sampling::Span::RuleParser.parse_json(settings.tracing.sampling.span_rules)
190
+ Tracing::Sampling::Span::Sampler.new(rules || [])
191
+ end
192
+
186
193
  def build_profiler(settings, agent_settings, tracer)
187
194
  return unless settings.profiling.enabled
188
195
 
@@ -423,7 +430,6 @@ module Datadog
423
430
  telemetry.emit_closing! unless replacement
424
431
  end
425
432
  end
426
- # rubocop:enable Metrics/ClassLength
427
433
  end
428
434
  end
429
435
  end
@@ -15,7 +15,6 @@ module Datadog
15
15
  # Global configuration settings for the trace library.
16
16
  # @public_api
17
17
  # rubocop:disable Metrics/BlockLength
18
- # rubocop:disable Metrics/ClassLength
19
18
  # rubocop:disable Layout/LineLength
20
19
  class Settings
21
20
  include Base
@@ -540,6 +539,7 @@ module Datadog
540
539
  option :sampler
541
540
 
542
541
  # Client-side sampling configuration.
542
+ # @see https://docs.datadoghq.com/tracing/trace_ingestion/mechanisms/
543
543
  # @public_api
544
544
  settings :sampling do
545
545
  # Default sampling rate for the tracer.
@@ -566,6 +566,48 @@ module Datadog
566
566
  o.default { env_to_float(Tracing::Configuration::Ext::Sampling::ENV_RATE_LIMIT, 100) }
567
567
  o.lazy
568
568
  end
569
+
570
+ # Single span sampling rules.
571
+ # These rules allow a span to be kept when its encompassing trace is dropped.
572
+ #
573
+ # The syntax for single span sampling rules can be found here:
574
+ # TODO: <Single Span Sampling documentation URL here>
575
+ #
576
+ # @default `DD_SPAN_SAMPLING_RULES` environment variable.
577
+ # Otherwise, `ENV_SPAN_SAMPLING_RULES_FILE` environment variable.
578
+ # Otherwise `nil`.
579
+ # @return [String,nil]
580
+ # @public_api
581
+ option :span_rules do |o|
582
+ o.default do
583
+ rules = ENV[Tracing::Configuration::Ext::Sampling::Span::ENV_SPAN_SAMPLING_RULES]
584
+ rules_file = ENV[Tracing::Configuration::Ext::Sampling::Span::ENV_SPAN_SAMPLING_RULES_FILE]
585
+
586
+ if rules
587
+ if rules_file
588
+ Datadog.logger.warn(
589
+ 'Both DD_SPAN_SAMPLING_RULES and DD_SPAN_SAMPLING_RULES_FILE were provided: only ' \
590
+ 'DD_SPAN_SAMPLING_RULES will be used. Please do not provide DD_SPAN_SAMPLING_RULES_FILE when ' \
591
+ 'also providing DD_SPAN_SAMPLING_RULES as their configuration conflicts. ' \
592
+ "DD_SPAN_SAMPLING_RULES_FILE=#{rules_file} DD_SPAN_SAMPLING_RULES=#{rules}"
593
+ )
594
+ end
595
+ rules
596
+ elsif rules_file
597
+ begin
598
+ File.read(rules_file)
599
+ rescue => e
600
+ # `File#read` errors have clear and actionable messages, no need to add extra exception info.
601
+ Datadog.logger.warn(
602
+ "Cannot read span sampling rules file `#{rules_file}`: #{e.message}." \
603
+ 'No span sampling rules will be applied.'
604
+ )
605
+ nil
606
+ end
607
+ end
608
+ end
609
+ o.lazy
610
+ end
569
611
  end
570
612
 
571
613
  # [Continuous Integration Visibility](https://docs.datadoghq.com/continuous_integration/) configuration.
@@ -618,6 +660,32 @@ module Datadog
618
660
  # @default `{}`
619
661
  # @return [Hash,nil]
620
662
  option :writer_options, default: ->(_i) { {} }, lazy: true
663
+
664
+ # Client IP configuration
665
+ # @public_api
666
+ settings :client_ip do
667
+ # Whether client IP collection is enabled. When enabled client IPs from HTTP requests will
668
+ # be reported in traces.
669
+ #
670
+ # @see https://docs.datadoghq.com/tracing/configure_data_security#configuring-a-client-ip-header
671
+ #
672
+ # @default The negated value of the `DD_TRACE_CLIENT_IP_HEADER_DISABLED` environment
673
+ # variable or `true` if it doesn't exist.
674
+ # @return [Boolean]
675
+ option :enabled do |o|
676
+ o.default { !env_to_bool(Tracing::Configuration::Ext::ClientIp::ENV_DISABLED, false) }
677
+ o.lazy
678
+ end
679
+
680
+ # An optional name of a custom header to resolve the client IP from.
681
+ #
682
+ # @default `DD_TRACE_CLIENT_IP_HEADER` environment variable, otherwise `nil`.
683
+ # @return [String,nil]
684
+ option :header_name do |o|
685
+ o.default { ENV.fetch(Tracing::Configuration::Ext::ClientIp::ENV_HEADER_NAME, nil) }
686
+ o.lazy
687
+ end
688
+ end
621
689
  end
622
690
 
623
691
  # The `version` tag in Datadog. Use it to enable [Deployment Tracking](https://docs.datadoghq.com/tracing/deployment_tracking/).
@@ -645,7 +713,6 @@ module Datadog
645
713
  end
646
714
  end
647
715
  # rubocop:enable Metrics/BlockLength
648
- # rubocop:enable Metrics/ClassLength
649
716
  # rubocop:enable Layout/LineLength
650
717
  end
651
718
  end
@@ -9,7 +9,7 @@ require_relative 'pin'
9
9
  module Datadog
10
10
  module Core
11
11
  # Configuration provides a unique access point for configurations
12
- module Configuration # rubocop:disable Metrics/ModuleLength
12
+ module Configuration
13
13
  include Kernel # Ensure that kernel methods are always available (https://sorbet.org/docs/error-reference#7003)
14
14
 
15
15
  # Used to ensure that @components initialization/reconfiguration is performed one-at-a-time, by a single thread.
@@ -0,0 +1,41 @@
1
+ module Datadog
2
+ module Core
3
+ # A some-what abstract class representing a collection of headers.
4
+ #
5
+ # Use the `HeaderCollection.from_hash` function to create a header collection from a `Hash`.
6
+ # Another option is to use `HashHeaderCollection` directly.
7
+ class HeaderCollection
8
+ # Gets a single value of the header with the given name, case insensitive.
9
+ #
10
+ # @param [String] header_name Name of the header to get the value of.
11
+ # @returns [String, nil] A single value of the header, or nil if the header with
12
+ # the given name is missing from the collection.
13
+ def get(header_name)
14
+ nil
15
+ end
16
+
17
+ # Create a header collection that retrieves headers from the given Hash.
18
+ #
19
+ # This can be useful for testing or other trivial use cases.
20
+ #
21
+ # @param [Hash] hash Hash with the headers.
22
+ def self.from_hash(hash)
23
+ HashHeaderCollection.new(hash)
24
+ end
25
+ end
26
+
27
+ # A header collection implementation that looks up headers in a Hash.
28
+ class HashHeaderCollection < HeaderCollection
29
+ def initialize(hash)
30
+ super()
31
+ @hash = {}.tap do |res|
32
+ hash.each_pair { |key, value| res[key.downcase] = value }
33
+ end
34
+ end
35
+
36
+ def get(header_name)
37
+ @hash[header_name.downcase]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -18,7 +18,6 @@ module Datadog
18
18
  module Core
19
19
  module Telemetry
20
20
  # Module defining methods for collecting metadata for telemetry
21
- # rubocop:disable Metrics/ModuleLength
22
21
  module Collector
23
22
  include Datadog::Core::Configuration
24
23
 
@@ -228,7 +227,6 @@ module Datadog
228
227
  end
229
228
  end
230
229
  end
231
- # rubocop:enable Metrics/ModuleLength
232
230
  end
233
231
  end
234
232
  end
@@ -8,7 +8,6 @@ module Datadog
8
8
  module Async
9
9
  # Adds threading behavior to workers
10
10
  # to run tasks asynchronously.
11
- # rubocop:disable Metrics/ModuleLength
12
11
  module Thread
13
12
  FORK_POLICY_STOP = :stop
14
13
  FORK_POLICY_RESTART = :restart
@@ -175,7 +174,6 @@ module Datadog
175
174
  end
176
175
  end
177
176
  end
178
- # rubocop:enable Metrics/ModuleLength
179
177
  end
180
178
  end
181
179
  end
@@ -15,7 +15,7 @@ module Datadog
15
15
  # Runs on its own background thread.
16
16
  #
17
17
  # This class has the prefix "Old" because it will be deprecated by the new native CPU Profiler
18
- class OldStack < Core::Worker # rubocop:disable Metrics/ClassLength
18
+ class OldStack < Core::Worker
19
19
  include Core::Workers::Polling
20
20
 
21
21
  DEFAULT_MAX_TIME_USAGE_PCT = 2.0
@@ -6,7 +6,7 @@ require_relative 'core/utils/only_once'
6
6
 
7
7
  module Datadog
8
8
  # Contains profiler for generating stack profiles, etc.
9
- module Profiling # rubocop:disable Metrics/ModuleLength
9
+ module Profiling
10
10
  GOOGLE_PROTOBUF_MINIMUM_VERSION = Gem::Version.new('3.0')
11
11
  private_constant :GOOGLE_PROTOBUF_MINIMUM_VERSION
12
12
 
@@ -0,0 +1,153 @@
1
+ # typed: true
2
+
3
+ require_relative '../core/configuration'
4
+ require_relative 'metadata/ext'
5
+ require_relative 'span'
6
+
7
+ require 'ipaddr'
8
+
9
+ module Datadog
10
+ module Tracing
11
+ # Common functions for supporting the `http.client_ip` span attribute.
12
+ module ClientIp
13
+ DEFAULT_IP_HEADERS_NAMES = %w[
14
+ x-forwarded-for
15
+ x-real-ip
16
+ x-client-ip
17
+ x-forwarded
18
+ x-cluster-client-ip
19
+ forwarded-for
20
+ forwarded
21
+ via
22
+ true-client-ip
23
+ ].freeze
24
+
25
+ TAG_MULTIPLE_IP_HEADERS = '_dd.multiple-ip-headers'.freeze
26
+
27
+ # Sets the `http.client_ip` tag on the given span.
28
+ #
29
+ # This function respects the user's settings: if they disable the client IP tagging,
30
+ # or provide a different IP header name.
31
+ #
32
+ # If multiple IP headers are present in the request, this function will instead set
33
+ # the `_dd.multiple-ip-headers` tag with the names of the present headers,
34
+ # and **NOT** set the `http.client_ip` tag.
35
+ #
36
+ # @param [Span] span The span that's associated with the request.
37
+ # @param [HeaderCollection, #get, nil] headers A collection with the request headers.
38
+ # @param [String, nil] remote_ip The remote IP the request associated with the span is sent to.
39
+ def self.set_client_ip_tag(span, headers: nil, remote_ip: nil)
40
+ return unless configuration.enabled
41
+
42
+ result = raw_ip_from_request(headers, remote_ip)
43
+
44
+ if result.raw_ip
45
+ ip = strip_decorations(result.raw_ip)
46
+ return unless valid_ip?(ip)
47
+
48
+ span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP, ip)
49
+ elsif result.multiple_ip_headers
50
+ span.set_tag(TAG_MULTIPLE_IP_HEADERS, result.multiple_ip_headers.keys.join(','))
51
+ end
52
+ end
53
+
54
+ IpExtractionResult = Struct.new(:raw_ip, :multiple_ip_headers)
55
+
56
+ # Returns a result struct that holds the raw client IP associated with the request if it was
57
+ # retrieved successfully.
58
+ #
59
+ # The client IP is looked up by the following logic:
60
+ # * If the user has configured a header name, return that header's value.
61
+ # * If exactly one of the known IP headers is present, return that header's value.
62
+ # * If none of the known IP headers are present, return the remote IP from the request.
63
+ #
64
+ # If more than one of the known IP headers is present, the result will have a `multiple_ip_headers`
65
+ # field with the name of the present IP headers.
66
+ #
67
+ # @param [Datadog::Core::HeaderCollection, #get, nil] headers The request headers
68
+ # @param [String] remote_ip The remote IP of the request.
69
+ # @return [IpExtractionResult] A struct that holds the unprocessed IP value,
70
+ # or `nil` if it wasn't found. Additionally, the `multiple_ip_headers` fields will hold the
71
+ # name of known IP headers present in the request if more than one of these were found.
72
+ def self.raw_ip_from_request(headers, remote_ip)
73
+ return IpExtractionResult.new(headers && headers.get(configuration.header_name), nil) if configuration.header_name
74
+
75
+ headers_present = ip_headers(headers)
76
+
77
+ case headers_present.size
78
+ when 0
79
+ IpExtractionResult.new(remote_ip, nil)
80
+ when 1
81
+ IpExtractionResult.new(headers_present.values.first, nil)
82
+ else
83
+ IpExtractionResult.new(nil, headers_present)
84
+ end
85
+ end
86
+
87
+ # Removes any port notations or zone specifiers from the IP address without
88
+ # verifying its validity.
89
+ def self.strip_decorations(address)
90
+ return strip_ipv4_port(address) if likely_ipv4?(address)
91
+
92
+ address = strip_ipv6_port(address)
93
+
94
+ strip_zone_specifier(address)
95
+ end
96
+
97
+ def self.strip_zone_specifier(ipv6)
98
+ ipv6.gsub(/%.*/, '')
99
+ end
100
+
101
+ def self.strip_ipv4_port(ip)
102
+ ip.gsub(/:\d+\z/, '')
103
+ end
104
+
105
+ def self.strip_ipv6_port(ip)
106
+ if /\[(.*)\](?::\d+)?/ =~ ip
107
+ Regexp.last_match(1)
108
+ else
109
+ ip
110
+ end
111
+ end
112
+
113
+ # Returns whether the given value is more likely to be an IPv4 than an IPv6 address.
114
+ #
115
+ # This is done by checking if a dot (`'.'`) character appears before a colon (`':'`) in the value.
116
+ # The rationale is that in valid IPv6 addresses, colons will always preced dots,
117
+ # and in valid IPv4 addresses dots will always preced colons.
118
+ def self.likely_ipv4?(value)
119
+ dot_index = value.index('.') || value.size
120
+ colon_index = value.index(':') || value.size
121
+
122
+ dot_index < colon_index
123
+ end
124
+
125
+ # Determines whether the given string is a valid IPv4 or IPv6 address.
126
+ def self.valid_ip?(ip)
127
+ # Client IPs should not have subnet masks even though IPAddr can parse them.
128
+ return false if ip.include?('/')
129
+
130
+ begin
131
+ IPAddr.new(ip)
132
+
133
+ true
134
+ rescue IPAddr::Error
135
+ false
136
+ end
137
+ end
138
+
139
+ def self.ip_headers(headers)
140
+ return {} unless headers
141
+
142
+ DEFAULT_IP_HEADERS_NAMES.each_with_object({}) do |name, result|
143
+ value = headers.get(name)
144
+ result[name] = value unless value.nil?
145
+ end
146
+ end
147
+
148
+ def self.configuration
149
+ Datadog.configuration.tracing.client_ip
150
+ end
151
+ end
152
+ end
153
+ end
@@ -32,6 +32,12 @@ module Datadog
32
32
  module Sampling
33
33
  ENV_SAMPLE_RATE = 'DD_TRACE_SAMPLE_RATE'.freeze
34
34
  ENV_RATE_LIMIT = 'DD_TRACE_RATE_LIMIT'.freeze
35
+
36
+ # @public_api
37
+ module Span
38
+ ENV_SPAN_SAMPLING_RULES = 'DD_SPAN_SAMPLING_RULES'.freeze
39
+ ENV_SPAN_SAMPLING_RULES_FILE = 'DD_SPAN_SAMPLING_RULES_FILE'.freeze
40
+ end
35
41
  end
36
42
 
37
43
  # @public_api
@@ -45,6 +51,12 @@ module Datadog
45
51
  ENV_DEFAULT_PORT = 'DD_TRACE_AGENT_PORT'.freeze
46
52
  ENV_DEFAULT_URL = 'DD_TRACE_AGENT_URL'.freeze
47
53
  end
54
+
55
+ # @public_api
56
+ module ClientIp
57
+ ENV_DISABLED = 'DD_TRACE_CLIENT_IP_HEADER_DISABLED'.freeze
58
+ ENV_HEADER_NAME = 'DD_TRACE_CLIENT_IP_HEADER'.freeze
59
+ end
48
60
  end
49
61
  end
50
62
  end