ddtrace 0.46.0 → 0.47.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 (70) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +52 -12
  3. data/.circleci/images/primary/{Dockerfile-jruby-9.2 → Dockerfile-jruby-9.2-latest} +2 -1
  4. data/.circleci/images/primary/Dockerfile-jruby-9.2.0.0 +73 -0
  5. data/.circleci/images/primary/Dockerfile-truffleruby-21.0.0 +73 -0
  6. data/.github/workflows/create-next-milestone.yml +2 -2
  7. data/.rubocop_todo.yml +3 -2
  8. data/.simplecov +6 -0
  9. data/Appraisals +1 -1
  10. data/CHANGELOG.md +83 -1
  11. data/Gemfile +19 -4
  12. data/LICENSE-3rdparty.csv +2 -0
  13. data/docker-compose.yml +75 -7
  14. data/docs/GettingStarted.md +61 -8
  15. data/lib/ddtrace/configuration.rb +92 -23
  16. data/lib/ddtrace/configuration/options.rb +2 -4
  17. data/lib/ddtrace/context_provider.rb +0 -2
  18. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +97 -26
  19. data/lib/ddtrace/contrib/aws/services.rb +1 -0
  20. data/lib/ddtrace/contrib/configurable.rb +63 -39
  21. data/lib/ddtrace/contrib/configuration/resolver.rb +70 -5
  22. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +19 -17
  23. data/lib/ddtrace/contrib/configuration/settings.rb +7 -6
  24. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -0
  25. data/lib/ddtrace/contrib/extensions.rb +26 -3
  26. data/lib/ddtrace/contrib/httpclient/instrumentation.rb +12 -16
  27. data/lib/ddtrace/contrib/httpclient/patcher.rb +5 -2
  28. data/lib/ddtrace/contrib/httprb/instrumentation.rb +12 -17
  29. data/lib/ddtrace/contrib/httprb/patcher.rb +5 -2
  30. data/lib/ddtrace/contrib/patcher.rb +8 -5
  31. data/lib/ddtrace/contrib/presto/patcher.rb +5 -2
  32. data/lib/ddtrace/contrib/rails/patcher.rb +6 -2
  33. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +11 -4
  34. data/lib/ddtrace/contrib/resque/integration.rb +1 -1
  35. data/lib/ddtrace/ext/runtime.rb +2 -0
  36. data/lib/ddtrace/patcher.rb +23 -1
  37. data/lib/ddtrace/pin.rb +5 -9
  38. data/lib/ddtrace/runtime/cgroup.rb +1 -1
  39. data/lib/ddtrace/runtime/container.rb +25 -27
  40. data/lib/ddtrace/runtime/identity.rb +8 -0
  41. data/lib/ddtrace/sync_writer.rb +5 -2
  42. data/lib/ddtrace/tracer.rb +6 -4
  43. data/lib/ddtrace/transport/http.rb +14 -5
  44. data/lib/ddtrace/transport/http/adapters/net.rb +18 -4
  45. data/lib/ddtrace/transport/http/builder.rb +5 -1
  46. data/lib/ddtrace/transport/http/env.rb +8 -0
  47. data/lib/ddtrace/transport/io/response.rb +1 -3
  48. data/lib/ddtrace/transport/io/traces.rb +6 -0
  49. data/lib/ddtrace/transport/traces.rb +15 -1
  50. data/lib/ddtrace/utils/compression.rb +27 -0
  51. data/lib/ddtrace/utils/object_set.rb +41 -0
  52. data/lib/ddtrace/utils/only_once.rb +40 -0
  53. data/lib/ddtrace/utils/sequence.rb +17 -0
  54. data/lib/ddtrace/utils/string_table.rb +45 -0
  55. data/lib/ddtrace/utils/time.rb +7 -0
  56. data/lib/ddtrace/vendor/multipart-post/LICENSE +11 -0
  57. data/lib/ddtrace/vendor/multipart-post/multipart.rb +12 -0
  58. data/lib/ddtrace/vendor/multipart-post/multipart/post.rb +8 -0
  59. data/lib/ddtrace/vendor/multipart-post/multipart/post/composite_read_io.rb +116 -0
  60. data/lib/ddtrace/vendor/multipart-post/multipart/post/multipartable.rb +57 -0
  61. data/lib/ddtrace/vendor/multipart-post/multipart/post/parts.rb +135 -0
  62. data/lib/ddtrace/vendor/multipart-post/multipart/post/version.rb +9 -0
  63. data/lib/ddtrace/vendor/multipart-post/net/http/post/multipart.rb +32 -0
  64. data/lib/ddtrace/version.rb +1 -1
  65. data/lib/ddtrace/workers/async.rb +3 -3
  66. data/lib/ddtrace/workers/loop.rb +14 -3
  67. data/lib/ddtrace/workers/queue.rb +1 -0
  68. data/lib/ddtrace/workers/trace_writer.rb +1 -0
  69. data/lib/ddtrace/writer.rb +4 -1
  70. metadata +21 -4
@@ -1,4 +1,5 @@
1
1
  require 'ddtrace/configuration/base'
2
+ require 'ddtrace/utils/only_once'
2
3
 
3
4
  module Datadog
4
5
  module Contrib
@@ -7,6 +8,8 @@ module Datadog
7
8
  class Settings
8
9
  include Datadog::Configuration::Base
9
10
 
11
+ DEPRECATION_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
12
+
10
13
  option :analytics_enabled, default: false
11
14
  option :analytics_sample_rate, default: 1.0
12
15
  option :enabled, default: true
@@ -14,7 +17,7 @@ module Datadog
14
17
  option :tracer do |o|
15
18
  o.delegate_to { Datadog.tracer }
16
19
  o.on_set do |_value|
17
- log_deprecation_warning(:tracer)
20
+ log_deprecation_warning
18
21
  end
19
22
  end
20
23
 
@@ -41,11 +44,9 @@ module Datadog
41
44
  the correct tracer internally.
42
45
  ).freeze
43
46
 
44
- include Datadog::Patcher # DEV includes #do_once here. We should move that logic to a generic component.
45
-
46
- def log_deprecation_warning(method_name)
47
- do_once(method_name) do
48
- Datadog.logger.warn("#{method_name}:#{DEPRECATION_WARNING}:#{caller.join("\n")}")
47
+ def log_deprecation_warning
48
+ DEPRECATION_WARN_ONLY_ONCE.run do
49
+ Datadog.logger.warn("tracer:#{DEPRECATION_WARNING}:#{caller.join("\n")}")
49
50
  end
50
51
  end
51
52
  end
@@ -1,3 +1,4 @@
1
+ require 'ddtrace/patcher'
1
2
  require 'ddtrace/contrib/patcher'
2
3
  require 'ddtrace/ext/app_types'
3
4
  require 'ddtrace/ext/integration'
@@ -47,7 +47,7 @@ module Datadog
47
47
  desc += ", Compatible? #{patch_results[:compatible]}"
48
48
  desc += ", Patchable? #{patch_results[:patchable]}"
49
49
 
50
- Datadog.logger.warn("Unable to patch #{patch_results['name']} (#{desc})")
50
+ Datadog.logger.warn("Unable to patch #{patch_results[:name]} (#{desc})")
51
51
  end
52
52
 
53
53
  target.integrations_pending_activation.clear
@@ -67,9 +67,32 @@ module Datadog
67
67
  end
68
68
  end
69
69
 
70
- def [](integration_name, configuration_name = :default)
70
+ # For the provided `integration_name`, resolves a matching configuration
71
+ # for the provided integration from an integration-specific `key`.
72
+ #
73
+ # How the matching is performed is integration-specific.
74
+ #
75
+ # @param [Symbol] integration_name the integration name
76
+ # @param [Object] key the integration-specific lookup key
77
+ # @return [Datadog::Contrib::Configuration::Settings]
78
+ def [](integration_name, key = :default)
71
79
  integration = fetch_integration(integration_name)
72
- integration.configuration(configuration_name) unless integration.nil?
80
+ integration.resolve(key) unless integration.nil?
81
+ end
82
+
83
+ # For the provided `integration_name`, retrieves a configuration previously
84
+ # stored by `#instrument`. Specifically, `describes` should be
85
+ # the same value provided in the `describes:` option for `#instrument`.
86
+ #
87
+ # If no `describes` value is provided, the default configuration is returned.
88
+ #
89
+ # @param [Symbol] integration_name the integration name
90
+ # @param [Object] describes the previously configured `describes:` object. If `nil`,
91
+ # fetches the default configuration
92
+ # @return [Datadog::Contrib::Configuration::Settings]
93
+ def configuration(integration_name, describes = nil)
94
+ integration = fetch_integration(integration_name)
95
+ integration.configuration(describes) unless integration.nil?
73
96
  end
74
97
 
75
98
  def instrument(integration_name, options = {}, &block)
@@ -88,14 +88,12 @@ module Datadog
88
88
  service = config[:service_name]
89
89
  tracer = config[:tracer]
90
90
 
91
- @datadog_pin ||= begin
92
- Datadog::Pin.new(
93
- service,
94
- app: Ext::APP,
95
- app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
96
- tracer: -> { config[:tracer] }
97
- )
98
- end
91
+ @datadog_pin ||= Datadog::Pin.new(
92
+ service,
93
+ app: Ext::APP,
94
+ app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
95
+ tracer: -> { config[:tracer] }
96
+ )
99
97
 
100
98
  if @datadog_pin.service_name == default_datadog_pin.service_name && @datadog_pin.service_name != service
101
99
  @datadog_pin.service = service
@@ -111,14 +109,12 @@ module Datadog
111
109
  config = Datadog.configuration[:httpclient]
112
110
  service = config[:service_name]
113
111
 
114
- @default_datadog_pin ||= begin
115
- Datadog::Pin.new(
116
- service,
117
- app: Ext::APP,
118
- app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
119
- tracer: -> { config[:tracer] }
120
- )
121
- end
112
+ @default_datadog_pin ||= Datadog::Pin.new(
113
+ service,
114
+ app: Ext::APP,
115
+ app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
116
+ tracer: -> { config[:tracer] }
117
+ )
122
118
  end
123
119
 
124
120
  def datadog_configuration(host = :default)
@@ -1,5 +1,6 @@
1
1
  require 'ddtrace/contrib/patcher'
2
2
  require 'ddtrace/contrib/httpclient/instrumentation'
3
+ require 'ddtrace/utils/only_once'
3
4
 
4
5
  module Datadog
5
6
  module Contrib
@@ -9,10 +10,12 @@ module Datadog
9
10
  module Patcher
10
11
  include Contrib::Patcher
11
12
 
13
+ PATCH_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
14
+
12
15
  module_function
13
16
 
14
17
  def patched?
15
- done?(:httpclient)
18
+ PATCH_ONLY_ONCE.ran?
16
19
  end
17
20
 
18
21
  def target_version
@@ -21,7 +24,7 @@ module Datadog
21
24
 
22
25
  # patch applies our patch
23
26
  def patch
24
- do_once(:httpclient) do
27
+ PATCH_ONLY_ONCE.run do
25
28
  begin
26
29
  ::HTTPClient.send(:include, Instrumentation)
27
30
  rescue StandardError => e
@@ -16,7 +16,6 @@ module Datadog
16
16
  end
17
17
 
18
18
  # Instance methods for configuration
19
- # rubocop:disable Metrics/ModuleLength
20
19
  module InstanceMethods
21
20
  include Datadog::Contrib::HttpAnnotationHelper
22
21
 
@@ -99,14 +98,12 @@ module Datadog
99
98
  service = config[:service_name]
100
99
  tracer = config[:tracer]
101
100
 
102
- @datadog_pin ||= begin
103
- Datadog::Pin.new(
104
- service,
105
- app: Ext::APP,
106
- app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
107
- tracer: -> { config[:tracer] }
108
- )
109
- end
101
+ @datadog_pin ||= Datadog::Pin.new(
102
+ service,
103
+ app: Ext::APP,
104
+ app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
105
+ tracer: -> { config[:tracer] }
106
+ )
110
107
 
111
108
  if @datadog_pin.service_name == default_datadog_pin.service_name && @datadog_pin.service_name != service
112
109
  @datadog_pin.service = service
@@ -122,14 +119,12 @@ module Datadog
122
119
  config = Datadog.configuration[:httprb]
123
120
  service = config[:service_name]
124
121
 
125
- @default_datadog_pin ||= begin
126
- Datadog::Pin.new(
127
- service,
128
- app: Ext::APP,
129
- app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
130
- tracer: -> { config[:tracer] }
131
- )
132
- end
122
+ @default_datadog_pin ||= Datadog::Pin.new(
123
+ service,
124
+ app: Ext::APP,
125
+ app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
126
+ tracer: -> { config[:tracer] }
127
+ )
133
128
  end
134
129
 
135
130
  def datadog_configuration(host = :default)
@@ -1,5 +1,6 @@
1
1
  require 'ddtrace/contrib/patcher'
2
2
  require 'ddtrace/contrib/httprb/instrumentation'
3
+ require 'ddtrace/utils/only_once'
3
4
 
4
5
  module Datadog
5
6
  module Contrib
@@ -9,10 +10,12 @@ module Datadog
9
10
  module Patcher
10
11
  include Contrib::Patcher
11
12
 
13
+ PATCH_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
14
+
12
15
  module_function
13
16
 
14
17
  def patched?
15
- done?(:httprb)
18
+ PATCH_ONLY_ONCE.ran?
16
19
  end
17
20
 
18
21
  def target_version
@@ -21,7 +24,7 @@ module Datadog
21
24
 
22
25
  # patch applies our patch
23
26
  def patch
24
- do_once(:httprb) do
27
+ PATCH_ONLY_ONCE.run do
25
28
  begin
26
29
  ::HTTP::Client.send(:include, Instrumentation)
27
30
  rescue StandardError => e
@@ -1,12 +1,10 @@
1
- require 'ddtrace/patcher'
1
+ require 'ddtrace/utils/only_once'
2
2
 
3
3
  module Datadog
4
4
  module Contrib
5
5
  # Common behavior for patcher modules
6
6
  module Patcher
7
7
  def self.included(base)
8
- base.send(:include, Datadog::Patcher)
9
-
10
8
  base.singleton_class.send(:prepend, CommonMethods)
11
9
  base.send(:prepend, CommonMethods) if base.instance_of?(Class)
12
10
  end
@@ -18,13 +16,13 @@ module Datadog
18
16
  end
19
17
 
20
18
  def patched?
21
- done?(:patch)
19
+ patch_only_once.ran?
22
20
  end
23
21
 
24
22
  def patch
25
23
  return unless defined?(super)
26
24
 
27
- do_once(:patch) do
25
+ patch_only_once.run do
28
26
  begin
29
27
  super.tap do
30
28
  # Emit a metric
@@ -56,6 +54,11 @@ module Datadog
56
54
  tags << "target_version:#{target_version}" if respond_to?(:target_version) && !target_version.nil?
57
55
  end
58
56
  end
57
+
58
+ def patch_only_once
59
+ # NOTE: This is not thread-safe
60
+ @patch_only_once ||= Datadog::Utils::OnlyOnce.new
61
+ end
59
62
  end
60
63
  end
61
64
  end
@@ -1,6 +1,7 @@
1
1
  require 'ddtrace/contrib/patcher'
2
2
  require 'ddtrace/contrib/presto/ext'
3
3
  require 'ddtrace/contrib/presto/instrumentation'
4
+ require 'ddtrace/utils/only_once'
4
5
 
5
6
  module Datadog
6
7
  module Contrib
@@ -9,14 +10,16 @@ module Datadog
9
10
  module Patcher
10
11
  include Contrib::Patcher
11
12
 
13
+ PATCH_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
14
+
12
15
  module_function
13
16
 
14
17
  def patched?
15
- done?(:presto)
18
+ PATCH_ONLY_ONCE.ran?
16
19
  end
17
20
 
18
21
  def patch
19
- do_once(:presto) do
22
+ PATCH_ONLY_ONCE.run do
20
23
  begin
21
24
  ::Presto::Client::Client.send(:include, Instrumentation::Client)
22
25
  rescue StandardError => e
@@ -3,6 +3,7 @@ require 'ddtrace/contrib/rails/framework'
3
3
  require 'ddtrace/contrib/rails/middlewares'
4
4
  require 'ddtrace/contrib/rails/log_injection'
5
5
  require 'ddtrace/contrib/rack/middlewares'
6
+ require 'ddtrace/utils/only_once'
6
7
 
7
8
  module Datadog
8
9
  module Contrib
@@ -11,6 +12,9 @@ module Datadog
11
12
  module Patcher
12
13
  include Contrib::Patcher
13
14
 
15
+ BEFORE_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Utils::OnlyOnce.new }
16
+ AFTER_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Utils::OnlyOnce.new }
17
+
14
18
  module_function
15
19
 
16
20
  def target_version
@@ -29,7 +33,7 @@ module Datadog
29
33
  end
30
34
 
31
35
  def before_intialize(app)
32
- do_once(:rails_before_initialize, for: app) do
36
+ BEFORE_INITIALIZE_ONLY_ONCE_PER_APP[app].run do
33
37
  # Middleware must be added before the application is initialized.
34
38
  # Otherwise the middleware stack will be frozen.
35
39
  # Sometimes we don't want to activate middleware e.g. OpenTracing, etc.
@@ -86,7 +90,7 @@ module Datadog
86
90
  end
87
91
 
88
92
  def after_intialize(app)
89
- do_once(:rails_after_initialize, for: app) do
93
+ AFTER_INITIALIZE_ONLY_ONCE_PER_APP[app].run do
90
94
  # Finish configuring the tracer after the application is initialized.
91
95
  # We need to wait for some things, like application name, middleware stack, etc.
92
96
  setup_tracer
@@ -6,12 +6,19 @@ module Datadog
6
6
  module Configuration
7
7
  UNIX_SCHEME = 'unix'.freeze
8
8
 
9
- # Converts Symbols, Strings, and Hashes to a normalized connection settings Hash.
9
+ # Converts String URLs and Hashes to a normalized connection settings Hash.
10
10
  class Resolver < Contrib::Configuration::Resolver
11
- def resolve(key_or_hash)
12
- return :default if key_or_hash == :default
11
+ # @param [Hash,String] Redis connection information
12
+ def resolve(hash)
13
+ super(parse_matcher(hash))
14
+ end
15
+
16
+ protected
17
+
18
+ def parse_matcher(matcher)
19
+ matcher = { url: matcher } if matcher.is_a?(String)
13
20
 
14
- normalize(connection_resolver.resolve(key_or_hash))
21
+ normalize(connection_resolver.resolve(matcher))
15
22
  end
16
23
 
17
24
  def normalize(hash)
@@ -25,7 +25,7 @@ module Datadog
25
25
 
26
26
  def self.compatible?
27
27
  super \
28
- && version >= Gem::Version.new('1.0') \
28
+ && version >= MINIMUM_VERSION \
29
29
  && version < MAXIMUM_VERSION
30
30
  end
31
31
 
@@ -5,7 +5,9 @@ module Datadog
5
5
  module Runtime
6
6
  # Identity
7
7
  LANG = 'ruby'.freeze
8
+ LANG_ENGINE = RUBY_ENGINE
8
9
  LANG_INTERPRETER = "#{RUBY_ENGINE}-#{RUBY_PLATFORM}".freeze
10
+ LANG_PLATFORM = RUBY_PLATFORM
9
11
  LANG_VERSION = RUBY_VERSION
10
12
  RUBY_ENGINE = ::RUBY_ENGINE # e.g. 'ruby', 'jruby', 'truffleruby'
11
13
  TRACER_VERSION = Datadog::VERSION::STRING
@@ -1,7 +1,21 @@
1
+ require 'ddtrace/utils/only_once'
2
+
1
3
  module Datadog
2
- # Defines some useful patching methods for integrations
4
+ # Deprecated: This module should no longer be included. It's only being kept around for backwards compatibility
5
+ # concerns regarding customer usage.
3
6
  module Patcher
7
+ INCLUDED_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
8
+ DO_ONCE_USAGE_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
9
+
4
10
  def self.included(base)
11
+ INCLUDED_WARN_ONLY_ONCE.run do
12
+ Datadog.logger.warn(
13
+ 'Including Datadog::Patcher is deprecated. ' \
14
+ 'For the #do_once behavior, use Datadog::Utils::OnlyOnce instead. ' \
15
+ 'For the #without_warnings behavior, use Datadog::Patcher.without_warnings { ... } as a module function.'
16
+ )
17
+ end
18
+
5
19
  base.send(:extend, CommonMethods)
6
20
  base.send(:include, CommonMethods)
7
21
  end
@@ -22,6 +36,10 @@ module Datadog
22
36
  end
23
37
 
24
38
  def do_once(key = nil, options = {})
39
+ DO_ONCE_USAGE_WARN_ONLY_ONCE.run do
40
+ Datadog.logger.warn('Datadog::Patcher#do_once is deprecated. Use Datadog::Utils::OnlyOnce instead.')
41
+ end
42
+
25
43
  # If already done, don't do again
26
44
  @done_once ||= Hash.new { |h, k| h[k] = {} }
27
45
  return @done_once[key][options[:for]] if @done_once.key?(key) && @done_once[key].key?(options[:for])
@@ -34,6 +52,10 @@ module Datadog
34
52
  end
35
53
 
36
54
  def done?(key, options = {})
55
+ DO_ONCE_USAGE_WARN_ONLY_ONCE.run do
56
+ Datadog.logger.warn('Datadog::Patcher#done? is deprecated. Use Datadog::Utils::OnlyOnce instead.')
57
+ end
58
+
37
59
  return false unless instance_variable_defined?(:@done_once)
38
60
 
39
61
  !@done_once.nil? && @done_once.key?(key) && @done_once[key].key?(options[:for])
data/lib/ddtrace/pin.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'ddtrace/patcher'
2
+ require 'ddtrace/utils/only_once'
2
3
 
3
4
  # \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
4
5
  module Datadog
@@ -7,6 +8,8 @@ module Datadog
7
8
  # This is useful if you wanted to, say, trace two different
8
9
  # database clusters.
9
10
  class Pin
11
+ DEPRECATION_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
12
+
10
13
  def self.get_from(obj)
11
14
  return nil unless obj.respond_to? :datadog_pin
12
15
 
@@ -74,15 +77,8 @@ module Datadog
74
77
  ).freeze
75
78
 
76
79
  def deprecation_warning
77
- log_deprecation_warning('Datadog::Pin.new')
78
- end
79
-
80
- include Datadog::Patcher
81
-
82
- def log_deprecation_warning(method_name)
83
- # Only log each deprecation warning once (safeguard against log spam)
84
- do_once(method_name) do
85
- Datadog.logger.warn("#{method_name}:#{DEPRECATION_WARNING}")
80
+ DEPRECATION_WARN_ONLY_ONCE.run do
81
+ Datadog.logger.warn("Datadog::Pin.new:#{DEPRECATION_WARNING}")
86
82
  end
87
83
  end
88
84
  end