ddtrace 0.26.1 → 0.27.0

Sign up to get free protection for your applications and to get access to all the features.
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