ddtrace 1.4.2 → 1.5.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 (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