ddtrace 0.40.0 → 0.45.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 (150) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +148 -130
  3. data/.circleci/images/primary/Dockerfile-3.0.0 +73 -0
  4. data/.github/workflows/add-milestone-to-pull-requests.yml +42 -0
  5. data/.github/workflows/create-next-milestone.yml +20 -0
  6. data/.simplecov +3 -0
  7. data/Appraisals +414 -135
  8. data/CHANGELOG.md +1112 -342
  9. data/CONTRIBUTING.md +2 -2
  10. data/Gemfile +4 -2
  11. data/README.md +1 -0
  12. data/Rakefile +231 -29
  13. data/ddtrace.gemspec +8 -8
  14. data/docker-compose.yml +30 -0
  15. data/docs/DevelopmentGuide.md +12 -2
  16. data/docs/GettingStarted.md +187 -16
  17. data/lib/ddtrace.rb +10 -0
  18. data/lib/ddtrace/auto_instrument.rb +3 -0
  19. data/lib/ddtrace/auto_instrument_base.rb +6 -0
  20. data/lib/ddtrace/buffer.rb +259 -52
  21. data/lib/ddtrace/configuration.rb +19 -0
  22. data/lib/ddtrace/configuration/options.rb +3 -1
  23. data/lib/ddtrace/configuration/settings.rb +9 -3
  24. data/lib/ddtrace/context.rb +18 -0
  25. data/lib/ddtrace/context_provider.rb +17 -5
  26. data/lib/ddtrace/contrib/action_cable/integration.rb +7 -0
  27. data/lib/ddtrace/contrib/action_pack/integration.rb +7 -0
  28. data/lib/ddtrace/contrib/action_view/event.rb +0 -4
  29. data/lib/ddtrace/contrib/action_view/events/render_partial.rb +1 -0
  30. data/lib/ddtrace/contrib/action_view/events/render_template.rb +1 -0
  31. data/lib/ddtrace/contrib/action_view/integration.rb +7 -0
  32. data/lib/ddtrace/contrib/active_record/events/sql.rb +4 -0
  33. data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
  34. data/lib/ddtrace/contrib/active_record/utils.rb +67 -21
  35. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +104 -3
  36. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +21 -0
  37. data/lib/ddtrace/contrib/active_support/ext.rb +3 -0
  38. data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
  39. data/lib/ddtrace/contrib/active_support/notifications/event.rb +10 -0
  40. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +2 -2
  41. data/lib/ddtrace/contrib/auto_instrument.rb +48 -0
  42. data/lib/ddtrace/contrib/aws/instrumentation.rb +6 -1
  43. data/lib/ddtrace/contrib/aws/patcher.rb +0 -1
  44. data/lib/ddtrace/contrib/aws/services.rb +1 -0
  45. data/lib/ddtrace/contrib/configurable.rb +2 -0
  46. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +6 -5
  47. data/lib/ddtrace/contrib/cucumber/configuration/settings.rb +38 -0
  48. data/lib/ddtrace/contrib/cucumber/ext.rb +19 -0
  49. data/lib/ddtrace/contrib/cucumber/formatter.rb +104 -0
  50. data/lib/ddtrace/contrib/cucumber/instrumentation.rb +24 -0
  51. data/lib/ddtrace/contrib/cucumber/integration.rb +45 -0
  52. data/lib/ddtrace/contrib/cucumber/patcher.rb +23 -0
  53. data/lib/ddtrace/contrib/dalli/instrumentation.rb +4 -0
  54. data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +2 -0
  55. data/lib/ddtrace/contrib/delayed_job/ext.rb +2 -0
  56. data/lib/ddtrace/contrib/delayed_job/plugin.rb +39 -15
  57. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +4 -0
  58. data/lib/ddtrace/contrib/ethon/easy_patch.rb +10 -7
  59. data/lib/ddtrace/contrib/ethon/ext.rb +1 -0
  60. data/lib/ddtrace/contrib/ethon/multi_patch.rb +4 -0
  61. data/lib/ddtrace/contrib/excon/middleware.rb +11 -1
  62. data/lib/ddtrace/contrib/extensions.rb +27 -1
  63. data/lib/ddtrace/contrib/faraday/middleware.rb +4 -0
  64. data/lib/ddtrace/contrib/faraday/patcher.rb +1 -1
  65. data/lib/ddtrace/contrib/grape/configuration/settings.rb +7 -0
  66. data/lib/ddtrace/contrib/grape/endpoint.rb +53 -18
  67. data/lib/ddtrace/contrib/grape/ext.rb +1 -0
  68. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +5 -1
  69. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +4 -0
  70. data/lib/ddtrace/contrib/http/instrumentation.rb +6 -2
  71. data/lib/ddtrace/contrib/httpclient/configuration/settings.rb +32 -0
  72. data/lib/ddtrace/contrib/httpclient/ext.rb +17 -0
  73. data/lib/ddtrace/contrib/httpclient/instrumentation.rb +152 -0
  74. data/lib/ddtrace/contrib/httpclient/integration.rb +43 -0
  75. data/lib/ddtrace/contrib/httpclient/patcher.rb +35 -0
  76. data/lib/ddtrace/contrib/httprb/instrumentation.rb +6 -3
  77. data/lib/ddtrace/contrib/kafka/event.rb +1 -1
  78. data/lib/ddtrace/contrib/mongodb/subscribers.rb +4 -0
  79. data/lib/ddtrace/contrib/mysql2/instrumentation.rb +4 -0
  80. data/lib/ddtrace/contrib/patchable.rb +18 -7
  81. data/lib/ddtrace/contrib/presto/instrumentation.rb +3 -0
  82. data/lib/ddtrace/contrib/qless/configuration/settings.rb +35 -0
  83. data/lib/ddtrace/contrib/qless/ext.rb +20 -0
  84. data/lib/ddtrace/contrib/qless/integration.rb +38 -0
  85. data/lib/ddtrace/contrib/qless/patcher.rb +35 -0
  86. data/lib/ddtrace/contrib/qless/qless_job.rb +72 -0
  87. data/lib/ddtrace/contrib/qless/tracer_cleaner.rb +32 -0
  88. data/lib/ddtrace/contrib/que/configuration/settings.rb +1 -0
  89. data/lib/ddtrace/contrib/que/tracer.rb +2 -1
  90. data/lib/ddtrace/contrib/racecar/event.rb +4 -0
  91. data/lib/ddtrace/contrib/rack/integration.rb +7 -0
  92. data/lib/ddtrace/contrib/rack/middlewares.rb +1 -1
  93. data/lib/ddtrace/contrib/rack/request_queue.rb +6 -1
  94. data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +10 -0
  95. data/lib/ddtrace/contrib/rails/patcher.rb +19 -5
  96. data/lib/ddtrace/contrib/rails/utils.rb +4 -0
  97. data/lib/ddtrace/contrib/rake/integration.rb +1 -1
  98. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +3 -1
  99. data/lib/ddtrace/contrib/redis/configuration/settings.rb +5 -0
  100. data/lib/ddtrace/contrib/redis/ext.rb +1 -0
  101. data/lib/ddtrace/contrib/redis/patcher.rb +20 -3
  102. data/lib/ddtrace/contrib/redis/quantize.rb +27 -0
  103. data/lib/ddtrace/contrib/redis/tags.rb +9 -1
  104. data/lib/ddtrace/contrib/resque/configuration/settings.rb +1 -0
  105. data/lib/ddtrace/contrib/resque/integration.rb +1 -1
  106. data/lib/ddtrace/contrib/resque/resque_job.rb +1 -1
  107. data/lib/ddtrace/contrib/rest_client/request_patch.rb +4 -0
  108. data/lib/ddtrace/contrib/rspec/configuration/settings.rb +38 -0
  109. data/lib/ddtrace/contrib/rspec/example.rb +61 -0
  110. data/lib/ddtrace/contrib/rspec/example_group.rb +61 -0
  111. data/lib/ddtrace/contrib/rspec/ext.rb +19 -0
  112. data/lib/ddtrace/contrib/rspec/integration.rb +46 -0
  113. data/lib/ddtrace/contrib/rspec/patcher.rb +25 -0
  114. data/lib/ddtrace/contrib/sequel/database.rb +3 -1
  115. data/lib/ddtrace/contrib/sequel/dataset.rb +3 -2
  116. data/lib/ddtrace/contrib/sequel/ext.rb +1 -0
  117. data/lib/ddtrace/contrib/sequel/utils.rb +16 -5
  118. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +1 -0
  119. data/lib/ddtrace/contrib/shoryuken/tracer.rb +4 -1
  120. data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +1 -0
  121. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +4 -1
  122. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +2 -2
  123. data/lib/ddtrace/contrib/sneakers/configuration/settings.rb +1 -0
  124. data/lib/ddtrace/contrib/sneakers/tracer.rb +17 -20
  125. data/lib/ddtrace/contrib/status_code_matcher.rb +67 -0
  126. data/lib/ddtrace/ext/app_types.rb +1 -0
  127. data/lib/ddtrace/ext/ci.rb +297 -0
  128. data/lib/ddtrace/ext/distributed.rb +8 -2
  129. data/lib/ddtrace/ext/git.rb +11 -0
  130. data/lib/ddtrace/ext/integration.rb +8 -0
  131. data/lib/ddtrace/ext/runtime.rb +2 -0
  132. data/lib/ddtrace/ext/test.rb +24 -0
  133. data/lib/ddtrace/opentracer/distributed_headers.rb +1 -1
  134. data/lib/ddtrace/propagation/grpc_propagator.rb +18 -6
  135. data/lib/ddtrace/propagation/http_propagator.rb +17 -2
  136. data/lib/ddtrace/runtime/identity.rb +4 -5
  137. data/lib/ddtrace/runtime/metrics.rb +6 -2
  138. data/lib/ddtrace/sampler.rb +2 -2
  139. data/lib/ddtrace/sampling/rate_limiter.rb +65 -16
  140. data/lib/ddtrace/span.rb +152 -27
  141. data/lib/ddtrace/tracer.rb +25 -13
  142. data/lib/ddtrace/transport/http/adapters/net.rb +8 -2
  143. data/lib/ddtrace/transport/http/statistics.rb +14 -1
  144. data/lib/ddtrace/transport/traces.rb +7 -2
  145. data/lib/ddtrace/utils.rb +16 -13
  146. data/lib/ddtrace/utils/forking.rb +52 -0
  147. data/lib/ddtrace/version.rb +1 -1
  148. data/lib/ddtrace/workers/runtime_metrics.rb +7 -3
  149. data/lib/ddtrace/writer.rb +19 -1
  150. metadata +111 -19
@@ -17,8 +17,11 @@ module Datadog
17
17
 
18
18
  def patch
19
19
  patch_cache_store_read
20
+ patch_cache_store_read_multi
20
21
  patch_cache_store_fetch
22
+ patch_cache_store_fetch_multi
21
23
  patch_cache_store_write
24
+ patch_cache_store_write_multi
22
25
  patch_cache_store_delete
23
26
  end
24
27
 
@@ -30,14 +33,32 @@ module Datadog
30
33
  cache_store_class(:read).send(:prepend, Cache::Instrumentation::Read)
31
34
  end
32
35
 
36
+ def patch_cache_store_read_multi
37
+ cache_store_class(:read_multi).send(:prepend, Cache::Instrumentation::ReadMulti)
38
+ end
39
+
33
40
  def patch_cache_store_fetch
34
41
  cache_store_class(:fetch).send(:prepend, Cache::Instrumentation::Fetch)
35
42
  end
36
43
 
44
+ def patch_cache_store_fetch_multi
45
+ klass = cache_store_class(:fetch_multi)
46
+ return unless klass.public_method_defined?(:fetch_multi)
47
+
48
+ klass.send(:prepend, Cache::Instrumentation::FetchMulti)
49
+ end
50
+
37
51
  def patch_cache_store_write
38
52
  cache_store_class(:write).send(:prepend, Cache::Instrumentation::Write)
39
53
  end
40
54
 
55
+ def patch_cache_store_write_multi
56
+ klass = cache_store_class(:write_multi)
57
+ return unless klass.public_method_defined?(:write_multi)
58
+
59
+ klass.send(:prepend, Cache::Instrumentation::WriteMulti)
60
+ end
61
+
41
62
  def patch_cache_store_delete
42
63
  cache_store_class(:delete).send(:prepend, Cache::Instrumentation::Delete)
43
64
  end
@@ -12,12 +12,15 @@ module Datadog
12
12
  QUANTIZE_CACHE_MAX_KEY_SIZE = 300
13
13
  RESOURCE_CACHE_DELETE = 'DELETE'.freeze
14
14
  RESOURCE_CACHE_GET = 'GET'.freeze
15
+ RESOURCE_CACHE_MGET = 'MGET'.freeze
15
16
  RESOURCE_CACHE_SET = 'SET'.freeze
17
+ RESOURCE_CACHE_MSET = 'MSET'.freeze
16
18
  SERVICE_CACHE = 'active_support-cache'.freeze
17
19
  SPAN_CACHE = 'rails.cache'.freeze
18
20
  SPAN_TYPE_CACHE = 'cache'.freeze
19
21
  TAG_CACHE_BACKEND = 'rails.cache.backend'.freeze
20
22
  TAG_CACHE_KEY = 'rails.cache.key'.freeze
23
+ TAG_CACHE_KEY_MULTI = 'rails.cache.keys'.freeze
21
24
  end
22
25
  end
23
26
  end
@@ -1,8 +1,8 @@
1
1
  require 'ddtrace/contrib/integration'
2
2
  require 'ddtrace/contrib/active_support/configuration/settings'
3
3
  require 'ddtrace/contrib/active_support/patcher'
4
-
5
4
  require 'ddtrace/contrib/active_support/cache/redis'
5
+ require 'ddtrace/contrib/rails/utils'
6
6
 
7
7
  module Datadog
8
8
  module Contrib
@@ -27,6 +27,12 @@ module Datadog
27
27
  super && version >= MINIMUM_VERSION
28
28
  end
29
29
 
30
+ # enabled by rails integration so should only auto instrument
31
+ # if detected that it is being used without rails
32
+ def auto_instrument?
33
+ !Datadog::Contrib::Rails::Utils.railtie_supported?
34
+ end
35
+
30
36
  def default_configuration
31
37
  Configuration::Settings.new
32
38
  end
@@ -56,6 +56,16 @@ module Datadog
56
56
  def tracer
57
57
  DEFAULT_TRACER
58
58
  end
59
+
60
+ def report_if_exception(span, payload)
61
+ exception = payload_exception(payload)
62
+ span.set_error(payload[:exception]) if exception
63
+ end
64
+
65
+ def payload_exception(payload)
66
+ payload[:exception_object] ||
67
+ payload[:exception] # Fallback for ActiveSupport < 5.0
68
+ end
59
69
  end
60
70
  end
61
71
  end
@@ -76,8 +76,8 @@ module Datadog
76
76
 
77
77
  # Start a trace
78
78
  tracer.trace(@span_name, @options.dup).tap do |span|
79
- # Assign start time if provided
80
- span.start_time = start unless start.nil?
79
+ # Start span if time is provided
80
+ span.start(start) unless start.nil?
81
81
  payload[:datadog_span] = span
82
82
  end
83
83
  end
@@ -0,0 +1,48 @@
1
+ require 'ddtrace'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ # Extensions for auto instrumentation added to the base library
6
+ # AutoInstrumentation enables all integration
7
+ module AutoInstrument
8
+ def self.extended(base)
9
+ base.send(:extend, Patch)
10
+ end
11
+
12
+ # Patch adds method for invoking auto_instrumentation
13
+ module Patch
14
+ def add_auto_instrument
15
+ super
16
+
17
+ if Datadog::Contrib::Rails::Utils.railtie_supported?
18
+ require 'ddtrace/contrib/rails/auto_instrument_railtie'
19
+ else
20
+ AutoInstrument.patch_all
21
+ end
22
+ AutoInstrument.patch_all
23
+ end
24
+ end
25
+
26
+ def self.patch_all
27
+ integrations = []
28
+
29
+ Datadog.registry.each do |integration|
30
+ # some instrumentations are automatically enabled when the `rails` instrumentation is enabled,
31
+ # patching them on their own automatically outside of the rails integration context would
32
+ # cause undesirable service naming, so we exclude them based their auto_instrument? setting.
33
+ # we also don't want to mix rspec/cucumber integration in as rspec is env we run tests in.
34
+ next unless integration.klass.auto_instrument?
35
+ integrations << integration.name
36
+ end
37
+
38
+ Datadog.configure do |c|
39
+ c.reduce_log_verbosity
40
+ # This will activate auto-instrumentation for Rails
41
+ integrations.each do |integration_name|
42
+ c.use integration_name
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,7 @@
1
1
  require 'ddtrace/contrib/analytics'
2
2
  require 'ddtrace/contrib/aws/ext'
3
+ require 'ddtrace/ext/http'
4
+ require 'ddtrace/ext/integration'
3
5
 
4
6
  module Datadog
5
7
  module Contrib
@@ -25,10 +27,13 @@ module Datadog
25
27
 
26
28
  def annotate!(span, context)
27
29
  span.service = configuration[:service_name]
28
- span.span_type = Datadog::Ext::AppTypes::WEB
30
+ span.span_type = Datadog::Ext::HTTP::TYPE_OUTBOUND
29
31
  span.name = Ext::SPAN_COMMAND
30
32
  span.resource = context.safely(:resource)
31
33
 
34
+ # Tag as an external peer service
35
+ span.set_tag(Datadog::Ext::Integration::TAG_PEER_SERVICE, span.service)
36
+
32
37
  # Set analytics sample rate
33
38
  if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
34
39
  Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
@@ -1,5 +1,4 @@
1
1
  require 'ddtrace/contrib/patcher'
2
- require 'ddtrace/ext/app_types'
3
2
  require 'ddtrace/contrib/aws/ext'
4
3
 
5
4
  module Datadog
@@ -104,6 +104,7 @@ module Datadog
104
104
  States
105
105
  StorageGateway
106
106
  Support
107
+ Textract
107
108
  WAF
108
109
  WAFRegional
109
110
  WorkDocs
@@ -28,6 +28,8 @@ module Datadog
28
28
 
29
29
  # If the key has matching configuration explicitly defined for it,
30
30
  # then return true. Otherwise return false.
31
+ # Note: a resolver's resolve method should not return a fallback value
32
+ # See: https://github.com/DataDog/dd-trace-rb/issues/1204
31
33
  def configuration_for?(key)
32
34
  key = resolver.resolve(key) unless key == :default
33
35
  configurations.key?(key)
@@ -8,19 +8,20 @@ module Datadog
8
8
  # Matches strings against Regexps.
9
9
  class PatternResolver < Datadog::Contrib::Configuration::Resolver
10
10
  def resolve(name)
11
+ return if patterns.empty?
12
+
11
13
  # Try to find a matching pattern
12
14
  matching_pattern = patterns.find do |pattern|
13
- # Rubocop incorrectly thinks assignment is done here...
14
- # rubocop:disable Style/ConditionalAssignment
15
15
  if pattern.is_a?(Proc)
16
- pattern === name
16
+ (pattern === name)
17
17
  else
18
- pattern === name.to_s # Co-erce to string
18
+ (pattern === name.to_s) ||
19
+ (pattern == name) # Only required during configuration time.
19
20
  end
20
21
  end
21
22
 
22
23
  # Return match or default
23
- matching_pattern || :default
24
+ matching_pattern
24
25
  end
25
26
 
26
27
  def add(pattern)
@@ -0,0 +1,38 @@
1
+ require 'ddtrace/contrib/configuration/settings'
2
+ require 'ddtrace/contrib/cucumber/ext'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module Cucumber
7
+ module Configuration
8
+ # Custom settings for the Cucumber integration
9
+ class Settings < Contrib::Configuration::Settings
10
+ option :enabled do |o|
11
+ o.default { env_to_bool(Ext::ENV_ENABLED, true) }
12
+ o.lazy
13
+ end
14
+
15
+ option :analytics_enabled do |o|
16
+ o.default { env_to_bool(Ext::ENV_ANALYTICS_ENABLED, true) }
17
+ o.lazy
18
+ end
19
+
20
+ option :analytics_sample_rate do |o|
21
+ o.default { env_to_float(Ext::ENV_ANALYTICS_SAMPLE_RATE, 1.0) }
22
+ o.lazy
23
+ end
24
+
25
+ option :service_name do |o|
26
+ o.default { Datadog.configuration.service || Ext::SERVICE_NAME }
27
+ o.lazy
28
+ end
29
+
30
+ option :operation_name do |o|
31
+ o.default { ENV.key?(Ext::ENV_OPERATION_NAME) ? ENV[Ext::ENV_OPERATION_NAME] : Ext::OPERATION_NAME }
32
+ o.lazy
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Cucumber
4
+ # Cucumber integration constants
5
+ module Ext
6
+ APP = 'cucumber'.freeze
7
+ ENV_ANALYTICS_ENABLED = 'DD_TRACE_CUCUMBER_ANALYTICS_ENABLED'.freeze
8
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_CUCUMBER_ANALYTICS_SAMPLE_RATE'.freeze
9
+ ENV_ENABLED = 'DD_TRACE_CUCUMBER_ENABLED'.freeze
10
+ ENV_OPERATION_NAME = 'DD_TRACE_CUCUMBER_OPERATION_NAME'.freeze
11
+ FRAMEWORK = 'cucumber'.freeze
12
+ OPERATION_NAME = 'cucumber.test'.freeze
13
+ SERVICE_NAME = 'cucumber'.freeze
14
+ STEP_SPAN_TYPE = 'step'.freeze
15
+ TEST_TYPE = 'test'.freeze
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,104 @@
1
+ require 'ddtrace/ext/app_types'
2
+ require 'ddtrace/ext/ci'
3
+ require 'ddtrace/ext/test'
4
+ require 'ddtrace/contrib/analytics'
5
+ require 'ddtrace/contrib/cucumber/ext'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module Cucumber
10
+ # Defines collection of instrumented Cucumber events
11
+ class Formatter
12
+ attr_reader :config
13
+ private :config
14
+
15
+ attr_reader :current_feature_span, :current_step_span
16
+ private :current_feature_span, :current_step_span
17
+
18
+ def initialize(config)
19
+ @config = config
20
+
21
+ bind_events(config)
22
+ end
23
+
24
+ def bind_events(config)
25
+ config.on_event :test_case_started, &method(:on_test_case_started)
26
+ config.on_event :test_case_finished, &method(:on_test_case_finished)
27
+ config.on_event :test_step_started, &method(:on_test_step_started)
28
+ config.on_event :test_step_finished, &method(:on_test_step_finished)
29
+ end
30
+
31
+ def on_test_case_started(event)
32
+ trace_options = {
33
+ app: Ext::APP,
34
+ resource: event.test_case.name,
35
+ service: configuration[:service_name],
36
+ span_type: Datadog::Ext::AppTypes::TEST,
37
+ tags: tags.merge(Datadog.configuration.tags)
38
+ }
39
+ @current_feature_span = tracer.trace(configuration[:operation_name], trace_options)
40
+ @current_feature_span.set_tag(Datadog::Ext::Test::TAG_FRAMEWORK, Ext::FRAMEWORK)
41
+ @current_feature_span.set_tag(Datadog::Ext::Test::TAG_NAME, event.test_case.name)
42
+ @current_feature_span.set_tag(Datadog::Ext::Test::TAG_SUITE, event.test_case.location.file)
43
+ @current_feature_span.set_tag(Datadog::Ext::Test::TAG_TYPE, Ext::TEST_TYPE)
44
+ @current_feature_span.set_tag(Datadog::Ext::Test::TAG_SPAN_KIND, Datadog::Ext::AppTypes::TEST)
45
+
46
+ # Set analytics sample rate
47
+ if Datadog::Contrib::Analytics.enabled?(configuration[:analytics_enabled])
48
+ Datadog::Contrib::Analytics.set_sample_rate(@current_feature_span, configuration[:analytics_sample_rate])
49
+ end
50
+
51
+ # Measure service stats
52
+ Contrib::Analytics.set_measured(@current_feature_span)
53
+ end
54
+
55
+ def on_test_case_finished(event)
56
+ return if @current_feature_span.nil?
57
+ @current_feature_span.status = 1 if event.result.failed?
58
+ @current_feature_span.set_tag(Datadog::Ext::Test::TAG_STATUS, status_from_result(event.result))
59
+ @current_feature_span.finish
60
+ end
61
+
62
+ def on_test_step_started(event)
63
+ trace_options = {
64
+ resource: event.test_step.to_s,
65
+ span_type: Ext::STEP_SPAN_TYPE
66
+ }
67
+ @current_step_span = tracer.trace(Ext::STEP_SPAN_TYPE, trace_options)
68
+ end
69
+
70
+ def on_test_step_finished(event)
71
+ return if @current_step_span.nil?
72
+ unless event.result.passed?
73
+ @current_step_span.set_error event.result.exception
74
+ end
75
+ @current_step_span.set_tag(Datadog::Ext::Test::TAG_STATUS, status_from_result(event.result))
76
+ @current_step_span.finish
77
+ end
78
+
79
+ private
80
+
81
+ def status_from_result(result)
82
+ if result.skipped?
83
+ return Datadog::Ext::Test::Status::SKIP
84
+ elsif result.ok?
85
+ return Datadog::Ext::Test::Status::PASS
86
+ end
87
+ Datadog::Ext::Test::Status::FAIL
88
+ end
89
+
90
+ def configuration
91
+ Datadog.configuration[:cucumber]
92
+ end
93
+
94
+ def tracer
95
+ configuration[:tracer]
96
+ end
97
+
98
+ def tags
99
+ @tags ||= Datadog::Ext::CI.tags(ENV)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,24 @@
1
+ require 'ddtrace/contrib/cucumber/formatter'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module Cucumber
6
+ # Instrumentation for Cucumber
7
+ module Instrumentation
8
+ def self.included(base)
9
+ base.send(:prepend, InstanceMethods)
10
+ end
11
+
12
+ # Instance methods for configuration
13
+ module InstanceMethods
14
+ attr_reader :datadog_formatter
15
+
16
+ def formatters
17
+ @datadog_formatter ||= Datadog::Contrib::Cucumber::Formatter.new(@configuration)
18
+ [@datadog_formatter] + super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require 'ddtrace/contrib/integration'
2
+ require 'ddtrace/contrib/cucumber/configuration/settings'
3
+ require 'ddtrace/contrib/cucumber/patcher'
4
+ require 'ddtrace/contrib/integration'
5
+
6
+ module Datadog
7
+ module Contrib
8
+ module Cucumber
9
+ # Description of Cucumber integration
10
+ class Integration
11
+ include Contrib::Integration
12
+
13
+ MINIMUM_VERSION = Gem::Version.new('3.0.0')
14
+
15
+ register_as :cucumber, auto_patch: true
16
+
17
+ def self.version
18
+ Gem.loaded_specs['cucumber'] \
19
+ && Gem.loaded_specs['cucumber'].version
20
+ end
21
+
22
+ def self.loaded?
23
+ !defined?(::Cucumber).nil? && !defined?(::Cucumber::Runtime).nil?
24
+ end
25
+
26
+ def self.compatible?
27
+ super && version >= MINIMUM_VERSION
28
+ end
29
+
30
+ # test environments should not auto instrument test libraries
31
+ def auto_instrument?
32
+ false
33
+ end
34
+
35
+ def default_configuration
36
+ Configuration::Settings.new
37
+ end
38
+
39
+ def patcher
40
+ Patcher
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end