ddtrace 1.4.2 → 1.5.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -3
  3. data/LICENSE-3rdparty.csv +1 -0
  4. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +0 -2
  5. data/lib/datadog/appsec/assets/waf_rules/recommended.json +1169 -275
  6. data/lib/datadog/appsec/assets/waf_rules/risky.json +78 -78
  7. data/lib/datadog/appsec/assets/waf_rules/strict.json +278 -88
  8. data/lib/datadog/appsec/configuration/settings.rb +0 -2
  9. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +25 -20
  10. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +11 -11
  11. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +11 -11
  12. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +11 -11
  13. data/lib/datadog/appsec/contrib/rack/request.rb +3 -0
  14. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +2 -1
  15. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -6
  16. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  17. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +11 -11
  18. data/lib/datadog/appsec/contrib/rails/request.rb +3 -0
  19. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +14 -12
  20. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +11 -11
  21. data/lib/datadog/appsec/event.rb +0 -8
  22. data/lib/datadog/appsec/instrumentation/gateway.rb +16 -2
  23. data/lib/datadog/appsec/processor.rb +18 -2
  24. data/lib/datadog/ci/ext/environment.rb +16 -4
  25. data/lib/datadog/core/configuration/agent_settings_resolver.rb +0 -3
  26. data/lib/datadog/core/configuration/components.rb +8 -2
  27. data/lib/datadog/core/configuration/settings.rb +71 -4
  28. data/lib/datadog/core/configuration.rb +1 -1
  29. data/lib/datadog/core/header_collection.rb +41 -0
  30. data/lib/datadog/core/telemetry/collector.rb +0 -2
  31. data/lib/datadog/core/workers/async.rb +0 -2
  32. data/lib/datadog/profiling/collectors/old_stack.rb +1 -1
  33. data/lib/datadog/profiling.rb +1 -1
  34. data/lib/datadog/tracing/client_ip.rb +153 -0
  35. data/lib/datadog/tracing/configuration/ext.rb +12 -0
  36. data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
  37. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +0 -2
  38. data/lib/datadog/tracing/contrib/ext.rb +19 -0
  39. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -2
  40. data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -2
  41. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -1
  42. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -4
  43. data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
  44. data/lib/datadog/tracing/contrib/rack/middlewares.rb +92 -38
  45. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +92 -10
  46. data/lib/datadog/tracing/flush.rb +57 -35
  47. data/lib/datadog/tracing/metadata/ext.rb +3 -9
  48. data/lib/datadog/tracing/metadata/tagging.rb +9 -0
  49. data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -0
  50. data/lib/datadog/tracing/sampling/rate_sampler.rb +10 -0
  51. data/lib/datadog/tracing/sampling/span/ext.rb +29 -0
  52. data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
  53. data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
  54. data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
  55. data/lib/datadog/tracing/sampling/span/sampler.rb +64 -0
  56. data/lib/datadog/tracing/span_operation.rb +0 -2
  57. data/lib/datadog/tracing/trace_operation.rb +22 -3
  58. data/lib/datadog/tracing/trace_segment.rb +1 -2
  59. data/lib/datadog/tracing/tracer.rb +31 -5
  60. data/lib/ddtrace/transport/traces.rb +2 -0
  61. data/lib/ddtrace/version.rb +2 -2
  62. metadata +21 -7
@@ -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
@@ -324,8 +323,8 @@ module Datadog
324
323
 
325
324
  # Parse tags from environment
326
325
  env_to_list(Core::Environment::Ext::ENV_TAGS, comma_separated_only: false).each do |tag|
327
- pair = tag.split(':')
328
- tags[pair.first] = pair.last if pair.length == 2
326
+ key, value = tag.split(':', 2)
327
+ tags[key] = value if value && !value.empty?
329
328
  end
330
329
 
331
330
  # Override tags if defined
@@ -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
@@ -3,7 +3,6 @@
3
3
  module Datadog
4
4
  module Tracing
5
5
  module Contrib
6
- # rubocop:disable Metrics/ModuleLength:
7
6
  module Aws
8
7
  SERVICES = %w[
9
8
  ACM
@@ -117,7 +116,6 @@ module Datadog
117
116
  XRay
118
117
  ].freeze
119
118
  end
120
- # rubocop:enable Metrics/ModuleLength:
121
119
  end
122
120
  end
123
121
  end
@@ -18,7 +18,6 @@ module Datadog
18
18
  end
19
19
 
20
20
  # InstanceMethods - implementing instrumentation
21
- # rubocop:disable Metrics/ModuleLength
22
21
  module InstanceMethods
23
22
  include Contrib::HttpAnnotationHelper
24
23
 
@@ -168,7 +167,6 @@ module Datadog
168
167
  datadog_configuration[:analytics_sample_rate]
169
168
  end
170
169
  end
171
- # rubocop:enable Metrics/ModuleLength
172
170
  end
173
171
  end
174
172
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ # Contrib specific constants
7
+ module Ext
8
+ # @public_api
9
+ module DB
10
+ TAG_INSTANCE = 'db.instance'
11
+ TAG_USER = 'db.user'
12
+ TAG_SYSTEM = 'db.system'
13
+ TAG_STATEMENT = 'db.statement'
14
+ TAG_ROW_COUNT = 'db.row_count'
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -39,8 +39,7 @@ module Datadog
39
39
 
40
40
  def annotate!(span, env, options)
41
41
  span.resource = resource_name(env)
42
- service_name(env[:url].host, options)
43
- span.service = options[:split_by_domain] ? env[:url].host : options[:service_name]
42
+ span.service = service_name(env[:url].host, options)
44
43
  span.span_type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
45
44
 
46
45
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
@@ -9,7 +9,6 @@ module Datadog
9
9
  module Tracing
10
10
  module Contrib
11
11
  module Grape
12
- # rubocop:disable Metrics/ModuleLength
13
12
  # Endpoint module includes a list of subscribers to create
14
13
  # traces when a Grape endpoint is hit
15
14
  module Endpoint
@@ -245,7 +244,6 @@ module Datadog
245
244
  end
246
245
  end
247
246
  end
248
- # rubocop:enable Metrics/ModuleLength
249
247
  end
250
248
  end
251
249
  end
@@ -27,7 +27,7 @@ module Datadog
27
27
  end
28
28
 
29
29
  option :schemas
30
- option :service_nam
30
+ option :service_name
31
31
  end
32
32
  end
33
33
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../../metadata/ext'
4
4
  require_relative '../analytics'
5
+ require_relative '../ext'
5
6
  require_relative 'ext'
6
7
 
7
8
  module Datadog
@@ -95,9 +96,9 @@ module Datadog
95
96
  span.set_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE, service)
96
97
  span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, host)
97
98
 
98
- span.set_tag(Tracing::Metadata::Ext::DB::TAG_INSTANCE, db)
99
- span.set_tag(Tracing::Metadata::Ext::DB::TAG_USER, user)
100
- span.set_tag(Tracing::Metadata::Ext::DB::TAG_SYSTEM, Ext::SPAN_SYSTEM)
99
+ span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, db)
100
+ span.set_tag(Contrib::Ext::DB::TAG_USER, user)
101
+ span.set_tag(Contrib::Ext::DB::TAG_SYSTEM, Ext::SPAN_SYSTEM)
101
102
 
102
103
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, host)
103
104
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, port)
@@ -106,7 +107,7 @@ module Datadog
106
107
  end
107
108
 
108
109
  def annotate_span_with_result!(span, result)
109
- span.set_tag(Tracing::Metadata::Ext::DB::TAG_ROW_COUNT, result.ntuples)
110
+ span.set_tag(Contrib::Ext::DB::TAG_ROW_COUNT, result.ntuples)
110
111
  end
111
112
 
112
113
  def datadog_configuration
@@ -0,0 +1,35 @@
1
+ require_relative '../../../core/header_collection'
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Rack
7
+ # Classes and utilities for handling headers in Rack.
8
+ module Header
9
+ # An implementation of a header collection that looks up headers from a Rack environment.
10
+ class RequestHeaderCollection < Datadog::Core::HeaderCollection
11
+ # Creates a header collection from a rack environment.
12
+ def initialize(env)
13
+ super()
14
+ @env = env
15
+ end
16
+
17
+ # Gets the value of the header with the given name.
18
+ def get(header_name)
19
+ @env[Header.to_rack_header(header_name)]
20
+ end
21
+
22
+ # Tests whether a header with the given name exists in the environment.
23
+ def key?(header_name)
24
+ @env.key?(Header.to_rack_header(header_name))
25
+ end
26
+ end
27
+
28
+ def self.to_rack_header(name)
29
+ "HTTP_#{name.to_s.upcase.gsub(/[-\s]/, '_')}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end