ddtrace 0.26.1 → 0.27.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +153 -77
  3. data/.circleci/images/primary/{Dockerfile-1.9.3 → Dockerfile-2.5.6} +8 -8
  4. data/.circleci/images/primary/Dockerfile-2.6.4 +73 -0
  5. data/.github/CODEOWNERS +1 -0
  6. data/Appraisals +201 -94
  7. data/CHANGELOG.md +25 -8
  8. data/Rakefile +153 -47
  9. data/ddtrace.gemspec +1 -1
  10. data/docker-compose.yml +56 -26
  11. data/docs/GettingStarted.md +117 -14
  12. data/lib/ddtrace.rb +4 -0
  13. data/lib/ddtrace/analytics.rb +9 -39
  14. data/lib/ddtrace/configuration.rb +0 -19
  15. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +144 -0
  16. data/lib/ddtrace/contrib/action_pack/action_controller/patcher.rb +37 -0
  17. data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +25 -0
  18. data/lib/ddtrace/contrib/action_pack/ext.rb +16 -0
  19. data/lib/ddtrace/contrib/action_pack/integration.rb +36 -0
  20. data/lib/ddtrace/contrib/action_pack/patcher.rb +29 -0
  21. data/lib/ddtrace/contrib/action_pack/utils.rb +36 -0
  22. data/lib/ddtrace/contrib/action_view/configuration/settings.rb +24 -0
  23. data/lib/ddtrace/contrib/action_view/ext.rb +17 -0
  24. data/lib/ddtrace/contrib/action_view/instrumentation.rb +192 -0
  25. data/lib/ddtrace/contrib/action_view/integration.rb +43 -0
  26. data/lib/ddtrace/contrib/action_view/patcher.rb +47 -0
  27. data/lib/ddtrace/contrib/action_view/utils.rb +32 -0
  28. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +157 -0
  29. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +62 -0
  30. data/lib/ddtrace/contrib/active_support/cache/redis.rb +47 -0
  31. data/lib/ddtrace/contrib/active_support/configuration/settings.rb +23 -0
  32. data/lib/ddtrace/contrib/active_support/ext.rb +21 -0
  33. data/lib/ddtrace/contrib/active_support/integration.rb +38 -0
  34. data/lib/ddtrace/contrib/active_support/patcher.rb +29 -0
  35. data/lib/ddtrace/contrib/ethon/configuration/settings.rb +24 -0
  36. data/lib/ddtrace/contrib/ethon/easy_patch.rb +139 -0
  37. data/lib/ddtrace/contrib/ethon/ext.rb +15 -0
  38. data/lib/ddtrace/contrib/ethon/integration.rb +35 -0
  39. data/lib/ddtrace/contrib/ethon/multi_patch.rb +80 -0
  40. data/lib/ddtrace/contrib/ethon/patcher.rb +27 -0
  41. data/lib/ddtrace/contrib/patchable.rb +1 -1
  42. data/lib/ddtrace/contrib/rails/configuration/settings.rb +43 -6
  43. data/lib/ddtrace/contrib/rails/ext.rb +0 -15
  44. data/lib/ddtrace/contrib/rails/framework.rb +37 -6
  45. data/lib/ddtrace/contrib/rails/middlewares.rb +2 -1
  46. data/lib/ddtrace/contrib/rails/patcher.rb +0 -8
  47. data/lib/ddtrace/contrib/rails/utils.rb +0 -46
  48. data/lib/ddtrace/contrib/redis/patcher.rb +12 -19
  49. data/lib/ddtrace/correlation.rb +8 -12
  50. data/lib/ddtrace/forced_tracing.rb +10 -38
  51. data/lib/ddtrace/sampler.rb +20 -74
  52. data/lib/ddtrace/span.rb +3 -4
  53. data/lib/ddtrace/tracer.rb +4 -11
  54. data/lib/ddtrace/version.rb +2 -2
  55. metadata +32 -9
  56. data/lib/ddtrace/contrib/rails/action_controller.rb +0 -100
  57. data/lib/ddtrace/contrib/rails/action_controller_patch.rb +0 -78
  58. data/lib/ddtrace/contrib/rails/action_view.rb +0 -19
  59. data/lib/ddtrace/contrib/rails/active_support.rb +0 -67
  60. data/lib/ddtrace/contrib/rails/core_extensions.rb +0 -353
@@ -0,0 +1,24 @@
1
+ require 'ddtrace/contrib/configuration/settings'
2
+ require 'ddtrace/contrib/ethon/ext'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module Ethon
7
+ module Configuration
8
+ # Custom settings for the Ethon integration
9
+ class Settings < Contrib::Configuration::Settings
10
+ option :analytics_enabled,
11
+ default: -> { env_to_bool(Ext::ENV_ANALYTICS_ENABLED, false) },
12
+ lazy: true
13
+
14
+ option :analytics_sample_rate,
15
+ default: -> { env_to_float(Ext::ENV_ANALYTICS_SAMPLE_RATE, 1.0) },
16
+ lazy: true
17
+
18
+ option :distributed_tracing, default: true
19
+ option :service_name, default: Ext::SERVICE_NAME
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,139 @@
1
+ require 'ddtrace/ext/net'
2
+ require 'ddtrace/ext/distributed'
3
+ require 'ddtrace/propagation/http_propagator'
4
+ require 'ddtrace/contrib/ethon/ext'
5
+
6
+ module Datadog
7
+ module Contrib
8
+ module Ethon
9
+ # Ethon EasyPatch
10
+ module EasyPatch
11
+ def self.included(base)
12
+ base.send(:prepend, InstanceMethods)
13
+ end
14
+
15
+ # InstanceMethods - implementing instrumentation
16
+ module InstanceMethods
17
+ def http_request(url, action_name, options = {})
18
+ return super unless tracer_enabled?
19
+
20
+ # It's tricky to get HTTP method from libcurl
21
+ @datadog_method = action_name.to_s.upcase
22
+ super
23
+ end
24
+
25
+ def headers=(headers)
26
+ return super unless tracer_enabled?
27
+
28
+ # Store headers to call this method again when span is ready
29
+ @datadog_original_headers = headers
30
+ super
31
+ end
32
+
33
+ def perform
34
+ return super unless tracer_enabled?
35
+ datadog_before_request
36
+ super
37
+ end
38
+
39
+ def complete
40
+ return super unless tracer_enabled?
41
+ begin
42
+ response_options = mirror.options
43
+ response_code = (response_options[:response_code] || response_options[:code]).to_i
44
+ if response_code.zero?
45
+ return_code = response_options[:return_code]
46
+ message = return_code ? ::Ethon::Curl.easy_strerror(return_code) : 'unknown reason'
47
+ set_span_error_message("Request has failed: #{message}")
48
+ else
49
+ @datadog_span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response_code)
50
+ if Datadog::Ext::HTTP::ERROR_RANGE.cover?(response_code)
51
+ set_span_error_message("Request has failed with HTTP error: #{response_code}")
52
+ end
53
+ end
54
+ ensure
55
+ @datadog_span.finish
56
+ @datadog_span = nil
57
+ end
58
+ super
59
+ end
60
+
61
+ def reset
62
+ super
63
+ ensure
64
+ if tracer_enabled?
65
+ @datadog_span = nil
66
+ @datadog_method = nil
67
+ @datadog_original_headers = nil
68
+ end
69
+ end
70
+
71
+ def datadog_before_request(parent_span: nil)
72
+ @datadog_span = datadog_configuration[:tracer].trace(
73
+ Ext::SPAN_REQUEST,
74
+ service: datadog_configuration[:service_name],
75
+ span_type: Datadog::Ext::HTTP::TYPE_OUTBOUND
76
+ )
77
+ @datadog_span.parent = parent_span unless parent_span.nil?
78
+
79
+ datadog_tag_request
80
+
81
+ if datadog_configuration[:distributed_tracing]
82
+ @datadog_original_headers ||= {}
83
+ Datadog::HTTPPropagator.inject!(@datadog_span.context, @datadog_original_headers)
84
+ self.headers = @datadog_original_headers
85
+ end
86
+ end
87
+
88
+ def datadog_span_started?
89
+ instance_variable_defined?(:@datadog_span) && !@datadog_span.nil?
90
+ end
91
+
92
+ private
93
+
94
+ def datadog_tag_request
95
+ span = @datadog_span
96
+ uri = URI.parse(url)
97
+ method = 'N/A'
98
+ if instance_variable_defined?(:@datadog_method) && !@datadog_method.nil?
99
+ method = @datadog_method.to_s
100
+ end
101
+ span.resource = method
102
+
103
+ # Set analytics sample rate
104
+ Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
105
+
106
+ span.set_tag(Datadog::Ext::HTTP::URL, uri.path)
107
+ span.set_tag(Datadog::Ext::HTTP::METHOD, method)
108
+ span.set_tag(Datadog::Ext::NET::TARGET_HOST, uri.host)
109
+ span.set_tag(Datadog::Ext::NET::TARGET_PORT, uri.port)
110
+ rescue URI::InvalidURIError
111
+ return
112
+ end
113
+
114
+ def set_span_error_message(message)
115
+ # Sets span error from message, in case there is no exception available
116
+ @datadog_span.status = Datadog::Ext::Errors::STATUS
117
+ @datadog_span.set_tag(Datadog::Ext::Errors::MSG, message)
118
+ end
119
+
120
+ def datadog_configuration
121
+ Datadog.configuration[:ethon]
122
+ end
123
+
124
+ def tracer_enabled?
125
+ datadog_configuration[:tracer].enabled
126
+ end
127
+
128
+ def analytics_enabled?
129
+ Contrib::Analytics.enabled?(datadog_configuration[:analytics_enabled])
130
+ end
131
+
132
+ def analytics_sample_rate
133
+ datadog_configuration[:analytics_sample_rate]
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,15 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Ethon
4
+ # Ethon integration constants
5
+ module Ext
6
+ APP = 'ethon'.freeze
7
+ ENV_ANALYTICS_ENABLED = 'DD_ETHON_ANALYTICS_ENABLED'.freeze
8
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_ETHON_ANALYTICS_SAMPLE_RATE'.freeze
9
+ SERVICE_NAME = 'ethon'.freeze
10
+ SPAN_REQUEST = 'ethon.request'.freeze
11
+ SPAN_MULTI_REQUEST = 'ethon.multi.request'.freeze
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'ddtrace/contrib/integration'
2
+ require 'ddtrace/contrib/ethon/configuration/settings'
3
+ require 'ddtrace/contrib/ethon/patcher'
4
+
5
+ module Datadog
6
+ module Contrib
7
+ module Ethon
8
+ # Description of Ethon integration
9
+ class Integration
10
+ include Contrib::Integration
11
+ register_as :ethon
12
+
13
+ def self.version
14
+ Gem.loaded_specs['ethon'] && Gem.loaded_specs['ethon'].version
15
+ end
16
+
17
+ def self.present?
18
+ super && defined?(::Ethon::Easy)
19
+ end
20
+
21
+ def self.compatible?
22
+ super && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
23
+ end
24
+
25
+ def default_configuration
26
+ Configuration::Settings.new
27
+ end
28
+
29
+ def patcher
30
+ Patcher
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,80 @@
1
+ require 'ddtrace/ext/net'
2
+ require 'ddtrace/ext/distributed'
3
+ require 'ddtrace/propagation/http_propagator'
4
+ require 'ddtrace/contrib/ethon/ext'
5
+
6
+ module Datadog
7
+ module Contrib
8
+ module Ethon
9
+ # Ethon MultiPatch
10
+ module MultiPatch
11
+ def self.included(base)
12
+ # No need to prepend here since add method is included into Multi class
13
+ base.send(:include, InstanceMethods)
14
+ end
15
+
16
+ # InstanceMethods - implementing instrumentation
17
+ module InstanceMethods
18
+ def add(easy)
19
+ handles = super
20
+ return handles if handles.nil? || !tracer_enabled?
21
+
22
+ if datadog_multi_performing?
23
+ # Start Easy span in case Multi is already performing
24
+ easy.datadog_before_request(parent_span: datadog_multi_span)
25
+ end
26
+ handles
27
+ end
28
+
29
+ def perform
30
+ if tracer_enabled?
31
+ easy_handles.each do |easy|
32
+ easy.datadog_before_request(parent_span: datadog_multi_span) unless easy.datadog_span_started?
33
+ end
34
+ end
35
+ super
36
+ ensure
37
+ if tracer_enabled? && datadog_multi_performing?
38
+ @datadog_multi_span.finish
39
+ @datadog_multi_span = nil
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def datadog_multi_performing?
46
+ instance_variable_defined?(:@datadog_multi_span) && !@datadog_multi_span.nil?
47
+ end
48
+
49
+ def datadog_multi_span
50
+ @datadog_multi_span ||= datadog_configuration[:tracer].trace(
51
+ Ext::SPAN_MULTI_REQUEST,
52
+ service: datadog_configuration[:service_name]
53
+ )
54
+
55
+ # Set analytics sample rate
56
+ Contrib::Analytics.set_sample_rate(@datadog_multi_span, analytics_sample_rate) if analytics_enabled?
57
+
58
+ @datadog_multi_span
59
+ end
60
+
61
+ def datadog_configuration
62
+ Datadog.configuration[:ethon]
63
+ end
64
+
65
+ def tracer_enabled?
66
+ datadog_configuration[:tracer].enabled
67
+ end
68
+
69
+ def analytics_enabled?
70
+ Contrib::Analytics.enabled?(datadog_configuration[:analytics_enabled])
71
+ end
72
+
73
+ def analytics_sample_rate
74
+ datadog_configuration[:analytics_sample_rate]
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,27 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Ethon
4
+ # Patcher enables patching of 'ethon' module.
5
+ module Patcher
6
+ include Contrib::Patcher
7
+
8
+ module_function
9
+
10
+ def patched?
11
+ done?(:ethon)
12
+ end
13
+
14
+ def patch
15
+ do_once(:ethon) do
16
+ require 'ddtrace/ext/app_types'
17
+ require 'ddtrace/contrib/ethon/easy_patch'
18
+ require 'ddtrace/contrib/ethon/multi_patch'
19
+
20
+ ::Ethon::Easy.send(:include, EasyPatch)
21
+ ::Ethon::Multi.send(:include, MultiPatch)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -18,7 +18,7 @@ module Datadog
18
18
  end
19
19
 
20
20
  def compatible?
21
- RUBY_VERSION >= '1.9.3' && present?
21
+ Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0') && present?
22
22
  end
23
23
  end
24
24
 
@@ -8,14 +8,34 @@ module Datadog
8
8
  class Settings < Contrib::Configuration::Settings
9
9
  option :analytics_enabled,
10
10
  default: -> { env_to_bool(Ext::ENV_ANALYTICS_ENABLED, nil) },
11
- lazy: true
11
+ lazy: true do |value|
12
+ value.tap do
13
+ # Update ActionPack analytics too
14
+ Datadog.configuration[:action_pack][:analytics_enabled] = value
15
+ end
16
+ end
12
17
 
13
18
  option :analytics_sample_rate,
14
19
  default: -> { env_to_float(Ext::ENV_ANALYTICS_SAMPLE_RATE, 1.0) },
15
- lazy: true
20
+ lazy: true do |value|
21
+ value.tap do
22
+ # Update ActionPack analytics too
23
+ Datadog.configuration[:action_pack][:analytics_sample_rate] = value
24
+ end
25
+ end
16
26
 
17
- option :cache_service
18
- option :controller_service
27
+ option :cache_service do |value|
28
+ value.tap do
29
+ # Update ActiveSupport service name too
30
+ Datadog.configuration[:active_support][:cache_service] = value
31
+ end
32
+ end
33
+ option :controller_service do |value|
34
+ value.tap do
35
+ # Update ActionPack service name too
36
+ Datadog.configuration[:action_pack][:controller_service] = value
37
+ end
38
+ end
19
39
  option :database_service, depends_on: [:service_name] do |value|
20
40
  value.tap do
21
41
  # Update ActiveRecord service name too
@@ -23,10 +43,27 @@ module Datadog
23
43
  end
24
44
  end
25
45
  option :distributed_tracing, default: true
26
- option :exception_controller, default: nil
46
+ option :exception_controller, default: nil do |value|
47
+ value.tap do
48
+ # Update ActionPack exception controller too
49
+ Datadog.configuration[:action_pack][:exception_controller] = value
50
+ end
51
+ end
27
52
  option :middleware, default: true
28
53
  option :middleware_names, default: false
29
- option :template_base_path, default: 'views/'
54
+ option :template_base_path, default: 'views/' do |value|
55
+ # Update ActionView template base path too
56
+ value.tap { Datadog.configuration[:action_view][:template_base_path] = value }
57
+ end
58
+
59
+ option :tracer, default: Datadog.tracer do |value|
60
+ value.tap do
61
+ Datadog.configuration[:active_record][:tracer] = value
62
+ Datadog.configuration[:active_support][:tracer] = value
63
+ Datadog.configuration[:action_pack][:tracer] = value
64
+ Datadog.configuration[:action_view][:tracer] = value
65
+ end
66
+ end
30
67
  end
31
68
  end
32
69
  end
@@ -6,21 +6,6 @@ module Datadog
6
6
  APP = 'rails'.freeze
7
7
  ENV_ANALYTICS_ENABLED = 'DD_RAILS_ANALYTICS_ENABLED'.freeze
8
8
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_RAILS_ANALYTICS_SAMPLE_RATE'.freeze
9
- QUANTIZE_CACHE_MAX_KEY_SIZE = 300
10
- RESOURCE_CACHE_DELETE = 'DELETE'.freeze
11
- RESOURCE_CACHE_GET = 'GET'.freeze
12
- RESOURCE_CACHE_SET = 'SET'.freeze
13
- SPAN_ACTION_CONTROLLER = 'rails.action_controller'.freeze
14
- SPAN_CACHE = 'rails.cache'.freeze
15
- SPAN_RENDER_PARTIAL = 'rails.render_partial'.freeze
16
- SPAN_RENDER_TEMPLATE = 'rails.render_template'.freeze
17
- SPAN_TYPE_CACHE = 'cache'.freeze
18
- TAG_CACHE_BACKEND = 'rails.cache.backend'.freeze
19
- TAG_CACHE_KEY = 'rails.cache.key'.freeze
20
- TAG_LAYOUT = 'rails.layout'.freeze
21
- TAG_ROUTE_ACTION = 'rails.route.action'.freeze
22
- TAG_ROUTE_CONTROLLER = 'rails.route.controller'.freeze
23
- TAG_TEMPLATE_NAME = 'rails.template_name'.freeze
24
9
  end
25
10
  end
26
11
  end
@@ -1,15 +1,13 @@
1
1
  require 'ddtrace/pin'
2
2
  require 'ddtrace/ext/app_types'
3
3
 
4
- require 'ddtrace/contrib/active_record/patcher'
4
+ require 'ddtrace/contrib/active_record/integration'
5
+ require 'ddtrace/contrib/active_support/integration'
6
+ require 'ddtrace/contrib/action_pack/integration'
7
+ require 'ddtrace/contrib/action_view/integration'
5
8
  require 'ddtrace/contrib/grape/endpoint'
6
- require 'ddtrace/contrib/rack/middlewares'
7
9
 
8
10
  require 'ddtrace/contrib/rails/ext'
9
- require 'ddtrace/contrib/rails/core_extensions'
10
- require 'ddtrace/contrib/rails/action_controller'
11
- require 'ddtrace/contrib/rails/action_view'
12
- require 'ddtrace/contrib/rails/active_support'
13
11
  require 'ddtrace/contrib/rails/utils'
14
12
 
15
13
  module Datadog
@@ -25,6 +23,9 @@ module Datadog
25
23
  config = config_with_defaults
26
24
 
27
25
  activate_rack!(config)
26
+ activate_active_support!(config)
27
+ activate_action_pack!(config)
28
+ activate_action_view!(config)
28
29
  activate_active_record!(config)
29
30
 
30
31
  # By default, default service would be guessed from the script
@@ -54,6 +55,36 @@ module Datadog
54
55
  )
55
56
  end
56
57
 
58
+ def self.activate_active_support!(config)
59
+ return unless defined?(::ActiveSupport)
60
+
61
+ Datadog.configuration.use(
62
+ :active_support,
63
+ cache_service: config[:cache_service],
64
+ tracer: config[:tracer]
65
+ )
66
+ end
67
+
68
+ def self.activate_action_pack!(config)
69
+ return unless defined?(::ActionPack)
70
+
71
+ Datadog.configuration.use(
72
+ :action_pack,
73
+ service_name: config[:service_name],
74
+ tracer: config[:tracer]
75
+ )
76
+ end
77
+
78
+ def self.activate_action_view!(config)
79
+ return unless defined?(::ActionView)
80
+
81
+ Datadog.configuration.use(
82
+ :action_view,
83
+ service_name: config[:service_name],
84
+ tracer: config[:tracer]
85
+ )
86
+ end
87
+
57
88
  def self.activate_active_record!(config)
58
89
  return unless defined?(::ActiveRecord)
59
90