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,47 @@
1
+ require 'ddtrace/ext/http'
2
+ require 'ddtrace/contrib/patcher'
3
+ require 'ddtrace/contrib/action_view/ext'
4
+ require 'ddtrace/contrib/action_view/instrumentation'
5
+ require 'ddtrace/contrib/action_view/utils'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActionView
10
+ # Patcher enables patching of ActionView module.
11
+ module Patcher
12
+ include Contrib::Patcher
13
+
14
+ module_function
15
+
16
+ def patched?
17
+ done?(:action_view)
18
+ end
19
+
20
+ def patch
21
+ do_once(:action_view) do
22
+ begin
23
+ patch_renderer
24
+ rescue StandardError => e
25
+ Datadog::Tracer.log.error("Unable to apply Action View integration: #{e} Location: #{e.backtrace.first}")
26
+ end
27
+ end
28
+ end
29
+
30
+ def patch_renderer
31
+ do_once(:patch_renderer) do
32
+ if defined?(::ActionView::TemplateRenderer) && defined?(::ActionView::PartialRenderer)
33
+ ::ActionView::TemplateRenderer.send(:prepend, Instrumentation::TemplateRenderer::Rails31Plus)
34
+ ::ActionView::PartialRenderer.send(:prepend, Instrumentation::PartialRenderer)
35
+ elsif defined?(::ActionView::Rendering) && defined?(::ActionView::Partials::PartialRenderer)
36
+ # NOTE: Rails < 3.1 compatibility: different classes are used
37
+ ::ActionView::Rendering.send(:prepend, Instrumentation::TemplateRenderer::Rails30)
38
+ ::ActionView::Partials::PartialRenderer.send(:prepend, Instrumentation::PartialRenderer)
39
+ else
40
+ Datadog::Tracer.log.debug('Expected Template/Partial classes not found; template rendering disabled')
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ require 'ddtrace/contrib/analytics'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module ActionView
6
+ # common utilities for Rails
7
+ module Utils
8
+ module_function
9
+
10
+ # in Rails the template name includes the template full path
11
+ # and it's better to avoid storing such information. This method
12
+ # returns the relative path from `views/` or the template name
13
+ # if a `views/` folder is not in the template full path. A wrong
14
+ # usage ensures that this method will not crash the tracing system.
15
+ def normalize_template_name(name)
16
+ return if name.nil?
17
+
18
+ base_path = Datadog.configuration[:action_view][:template_base_path]
19
+ sections_view = name.split(base_path)
20
+
21
+ if sections_view.length == 1
22
+ name.split('/')[-1]
23
+ else
24
+ sections_view[-1]
25
+ end
26
+ rescue
27
+ return name.to_s
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,157 @@
1
+ require 'ddtrace/contrib/active_support/ext'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module ActiveSupport
6
+ module Cache
7
+ # Defines instrumentation for ActiveSupport caching
8
+ # rubocop:disable Lint/RescueException
9
+ module Instrumentation
10
+ module_function
11
+
12
+ def start_trace_cache(payload)
13
+ tracer = Datadog.configuration[:active_support][:tracer]
14
+
15
+ # In most of the cases Rails ``fetch()`` and ``read()`` calls are nested.
16
+ # This check ensures that two reads are not nested since they don't provide
17
+ # interesting details.
18
+ # NOTE: the ``finish_trace_cache()`` is fired but it already has a safe-guard
19
+ # to avoid any kind of issue.
20
+ current_span = tracer.active_span
21
+ return if payload[:action] == Ext::RESOURCE_CACHE_GET &&
22
+ current_span.try(:name) == Ext::SPAN_CACHE &&
23
+ current_span.try(:resource) == Ext::RESOURCE_CACHE_GET
24
+
25
+ tracing_context = payload.fetch(:tracing_context)
26
+
27
+ # create a new ``Span`` and add it to the tracing context
28
+ service = Datadog.configuration[:active_support][:cache_service]
29
+ type = Ext::SPAN_TYPE_CACHE
30
+ span = tracer.trace(Ext::SPAN_CACHE, service: service, span_type: type)
31
+ span.resource = payload.fetch(:action)
32
+ tracing_context[:dd_cache_span] = span
33
+ rescue StandardError => e
34
+ Datadog::Tracer.log.debug(e.message)
35
+ end
36
+
37
+ def finish_trace_cache(payload)
38
+ # retrieve the tracing context and continue the trace
39
+ tracing_context = payload.fetch(:tracing_context)
40
+ span = tracing_context[:dd_cache_span]
41
+ return unless span && !span.finished?
42
+
43
+ begin
44
+ # discard parameters from the cache_store configuration
45
+ if defined?(::Rails)
46
+ store, = *Array.wrap(::Rails.configuration.cache_store).flatten
47
+ span.set_tag(Ext::TAG_CACHE_BACKEND, store)
48
+ end
49
+
50
+ normalized_key = ::ActiveSupport::Cache.expand_cache_key(payload.fetch(:key))
51
+ cache_key = Datadog::Utils.truncate(normalized_key, Ext::QUANTIZE_CACHE_MAX_KEY_SIZE)
52
+ span.set_tag(Ext::TAG_CACHE_KEY, cache_key)
53
+
54
+ span.set_error(payload[:exception]) if payload[:exception]
55
+ ensure
56
+ span.finish
57
+ end
58
+ rescue StandardError => e
59
+ Datadog::Tracer.log.debug(e.message)
60
+ end
61
+
62
+ # Defines instrumentation for ActiveSupport cache reading
63
+ module Read
64
+ def read(*args, &block)
65
+ payload = {
66
+ action: Ext::RESOURCE_CACHE_GET,
67
+ key: args[0],
68
+ tracing_context: {}
69
+ }
70
+
71
+ begin
72
+ # process and catch cache exceptions
73
+ Instrumentation.start_trace_cache(payload)
74
+ super
75
+ rescue Exception => e
76
+ payload[:exception] = [e.class.name, e.message]
77
+ payload[:exception_object] = e
78
+ raise e
79
+ end
80
+ ensure
81
+ Instrumentation.finish_trace_cache(payload)
82
+ end
83
+ end
84
+
85
+ # Defines instrumentation for ActiveSupport cache fetching
86
+ module Fetch
87
+ def fetch(*args, &block)
88
+ payload = {
89
+ action: Ext::RESOURCE_CACHE_GET,
90
+ key: args[0],
91
+ tracing_context: {}
92
+ }
93
+
94
+ begin
95
+ # process and catch cache exceptions
96
+ Instrumentation.start_trace_cache(payload)
97
+ super
98
+ rescue Exception => e
99
+ payload[:exception] = [e.class.name, e.message]
100
+ payload[:exception_object] = e
101
+ raise e
102
+ end
103
+ ensure
104
+ Instrumentation.finish_trace_cache(payload)
105
+ end
106
+ end
107
+
108
+ # Defines instrumentation for ActiveSupport cache writing
109
+ module Write
110
+ def write(*args, &block)
111
+ payload = {
112
+ action: Ext::RESOURCE_CACHE_SET,
113
+ key: args[0],
114
+ tracing_context: {}
115
+ }
116
+
117
+ begin
118
+ # process and catch cache exceptions
119
+ Instrumentation.start_trace_cache(payload)
120
+ super
121
+ rescue Exception => e
122
+ payload[:exception] = [e.class.name, e.message]
123
+ payload[:exception_object] = e
124
+ raise e
125
+ end
126
+ ensure
127
+ Instrumentation.finish_trace_cache(payload)
128
+ end
129
+ end
130
+
131
+ # Defines instrumentation for ActiveSupport cache deleting
132
+ module Delete
133
+ def delete(*args, &block)
134
+ payload = {
135
+ action: Ext::RESOURCE_CACHE_DELETE,
136
+ key: args[0],
137
+ tracing_context: {}
138
+ }
139
+
140
+ begin
141
+ # process and catch cache exceptions
142
+ Instrumentation.start_trace_cache(payload)
143
+ super
144
+ rescue Exception => e
145
+ payload[:exception] = [e.class.name, e.message]
146
+ payload[:exception_object] = e
147
+ raise e
148
+ end
149
+ ensure
150
+ Instrumentation.finish_trace_cache(payload)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,62 @@
1
+ require 'ddtrace/contrib/patcher'
2
+ require 'ddtrace/contrib/active_support/cache/instrumentation'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module ActiveSupport
7
+ module Cache
8
+ # Patcher enables patching of 'active_support' module.
9
+ module Patcher
10
+ include Contrib::Patcher
11
+
12
+ module_function
13
+
14
+ def patched?
15
+ done?(:cache)
16
+ end
17
+
18
+ def patch
19
+ do_once(:cache) do
20
+ begin
21
+ patch_cache_store_read
22
+ patch_cache_store_fetch
23
+ patch_cache_store_write
24
+ patch_cache_store_delete
25
+ rescue StandardError => e
26
+ Datadog::Tracer.log.error("Unable to apply Active Support cache integration: #{e}")
27
+ end
28
+ end
29
+ end
30
+
31
+ def cache_store_class(meth)
32
+ ::ActiveSupport::Cache::Store
33
+ end
34
+
35
+ def patch_cache_store_read
36
+ do_once(:patch_cache_store_read) do
37
+ cache_store_class(:read).send(:prepend, Cache::Instrumentation::Read)
38
+ end
39
+ end
40
+
41
+ def patch_cache_store_fetch
42
+ do_once(:patch_cache_store_fetch) do
43
+ cache_store_class(:fetch).send(:prepend, Cache::Instrumentation::Fetch)
44
+ end
45
+ end
46
+
47
+ def patch_cache_store_write
48
+ do_once(:patch_cache_store_write) do
49
+ cache_store_class(:write).send(:prepend, Cache::Instrumentation::Write)
50
+ end
51
+ end
52
+
53
+ def patch_cache_store_delete
54
+ do_once(:patch_cache_store_delete) do
55
+ cache_store_class(:delete).send(:prepend, Cache::Instrumentation::Delete)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,47 @@
1
+ require 'ddtrace/contrib/active_support/cache/patcher'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module ActiveSupport
6
+ module Cache
7
+ # Support for Redis with ActiveSupport
8
+ module Redis
9
+ # Patching behavior for Redis with ActiveSupport
10
+ module Patcher
11
+ # For Rails < 5.2 w/ redis-activesupport...
12
+ # When Redis is used, we can't only patch Cache::Store as it is
13
+ # Cache::RedisStore, a sub-class of it that is used, in practice.
14
+ # We need to do a per-method monkey patching as some of them might
15
+ # be redefined, and some of them not. The latest version of redis-activesupport
16
+ # redefines write but leaves untouched read and delete:
17
+ # https://github.com/redis-store/redis-activesupport/blob/master/lib/active_support/cache/redis_store.rb
18
+ #
19
+ # For Rails >= 5.2 w/o redis-activesupport...
20
+ # ActiveSupport includes a Redis cache store internally, and does not require these overrides.
21
+ # https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/redis_cache_store.rb
22
+ def patch_redis?(meth)
23
+ !Gem.loaded_specs['redis-activesupport'].nil? \
24
+ && defined?(::ActiveSupport::Cache::RedisStore) \
25
+ && ::ActiveSupport::Cache::RedisStore.instance_methods(false).include?(meth)
26
+ end
27
+
28
+ def cache_store_class(meth)
29
+ if patch_redis?(meth)
30
+ ::ActiveSupport::Cache::RedisStore
31
+ else
32
+ super
33
+ end
34
+ end
35
+ end
36
+
37
+ # Decorate Cache patcher with Redis support
38
+ Cache::Patcher.instance_eval do
39
+ class << self
40
+ prepend Redis::Patcher
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,23 @@
1
+ require 'ddtrace/contrib/configuration/settings'
2
+ require 'ddtrace/contrib/active_support/ext'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module ActiveSupport
7
+ module Configuration
8
+ # Custom settings for the ActiveSupport 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 :cache_service, default: Ext::SERVICE_CACHE
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module Datadog
2
+ module Contrib
3
+ module ActiveSupport
4
+ # ActiveSupport integration constants
5
+ module Ext
6
+ APP = 'active_support'.freeze
7
+ ENV_ANALYTICS_ENABLED = 'DD_ACTIVE_SUPPORT_ANALYTICS_ENABLED'.freeze
8
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_ACTIVE_SUPPORT_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
+ SERVICE_CACHE = 'active_support-cache'.freeze
14
+ SPAN_CACHE = 'rails.cache'.freeze
15
+ SPAN_TYPE_CACHE = 'cache'.freeze
16
+ TAG_CACHE_BACKEND = 'rails.cache.backend'.freeze
17
+ TAG_CACHE_KEY = 'rails.cache.key'.freeze
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ require 'ddtrace/contrib/integration'
2
+ require 'ddtrace/contrib/active_support/configuration/settings'
3
+ require 'ddtrace/contrib/active_support/patcher'
4
+
5
+ require 'ddtrace/contrib/active_support/cache/redis'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActiveSupport
10
+ # Describes the ActiveSupport integration
11
+ class Integration
12
+ include Contrib::Integration
13
+
14
+ register_as :active_support, auto_patch: false
15
+
16
+ def self.version
17
+ Gem.loaded_specs['activesupport'] && Gem.loaded_specs['activesupport'].version
18
+ end
19
+
20
+ def self.present?
21
+ super && defined?(::ActiveSupport)
22
+ end
23
+
24
+ def self.compatible?
25
+ super && version >= Gem::Version.new('3.0')
26
+ end
27
+
28
+ def default_configuration
29
+ Configuration::Settings.new
30
+ end
31
+
32
+ def patcher
33
+ ActiveSupport::Patcher
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ require 'ddtrace/contrib/patcher'
2
+ require 'ddtrace/contrib/active_support/cache/patcher'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module ActiveSupport
7
+ # Patcher enables patching of 'active_support' module.
8
+ module Patcher
9
+ include Contrib::Patcher
10
+
11
+ module_function
12
+
13
+ def patched?
14
+ done?(:active_support)
15
+ end
16
+
17
+ def patch
18
+ do_once(:active_support) do
19
+ begin
20
+ Cache::Patcher.patch
21
+ rescue StandardError => e
22
+ Datadog::Tracer.log.error("Unable to apply Active Support integration: #{e}")
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end