ddtrace 0.32.0 → 0.33.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 (65) hide show
  1. checksums.yaml +5 -5
  2. data/.env +2 -0
  3. data/Appraisals +9 -6
  4. data/CHANGELOG.md +32 -1
  5. data/Rakefile +3 -2
  6. data/ddtrace.gemspec +2 -1
  7. data/docker-compose.yml +9 -0
  8. data/docs/GettingStarted.md +69 -6
  9. data/lib/ddtrace.rb +1 -0
  10. data/lib/ddtrace/configuration/option.rb +3 -2
  11. data/lib/ddtrace/configuration/option_definition.rb +1 -1
  12. data/lib/ddtrace/configuration/options.rb +5 -0
  13. data/lib/ddtrace/contrib/action_cable/integration.rb +2 -2
  14. data/lib/ddtrace/contrib/action_pack/integration.rb +2 -2
  15. data/lib/ddtrace/contrib/action_view/integration.rb +2 -2
  16. data/lib/ddtrace/contrib/active_model_serializers/integration.rb +3 -5
  17. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +4 -5
  18. data/lib/ddtrace/contrib/active_record/integration.rb +2 -2
  19. data/lib/ddtrace/contrib/active_support/integration.rb +2 -2
  20. data/lib/ddtrace/contrib/aws/integration.rb +6 -2
  21. data/lib/ddtrace/contrib/aws/patcher.rb +8 -2
  22. data/lib/ddtrace/contrib/concurrent_ruby/integration.rb +6 -2
  23. data/lib/ddtrace/contrib/configurable.rb +30 -13
  24. data/lib/ddtrace/contrib/configuration/resolver.rb +7 -3
  25. data/lib/ddtrace/contrib/dalli/integration.rb +2 -2
  26. data/lib/ddtrace/contrib/delayed_job/integration.rb +6 -2
  27. data/lib/ddtrace/contrib/elasticsearch/integration.rb +2 -2
  28. data/lib/ddtrace/contrib/ethon/integration.rb +6 -2
  29. data/lib/ddtrace/contrib/excon/integration.rb +6 -2
  30. data/lib/ddtrace/contrib/faraday/integration.rb +2 -2
  31. data/lib/ddtrace/contrib/grape/integration.rb +3 -3
  32. data/lib/ddtrace/contrib/graphql/integration.rb +3 -5
  33. data/lib/ddtrace/contrib/grpc/integration.rb +2 -2
  34. data/lib/ddtrace/contrib/http/integration.rb +4 -0
  35. data/lib/ddtrace/contrib/mongodb/integration.rb +2 -2
  36. data/lib/ddtrace/contrib/mysql2/integration.rb +6 -2
  37. data/lib/ddtrace/contrib/patchable.rb +21 -4
  38. data/lib/ddtrace/contrib/presto/configuration/settings.rb +23 -0
  39. data/lib/ddtrace/contrib/presto/ext.rb +25 -0
  40. data/lib/ddtrace/contrib/presto/instrumentation.rb +107 -0
  41. data/lib/ddtrace/contrib/presto/integration.rb +36 -0
  42. data/lib/ddtrace/contrib/presto/patcher.rb +30 -0
  43. data/lib/ddtrace/contrib/racecar/integration.rb +3 -3
  44. data/lib/ddtrace/contrib/rack/integration.rb +6 -2
  45. data/lib/ddtrace/contrib/rails/integration.rb +6 -3
  46. data/lib/ddtrace/contrib/rake/integration.rb +6 -2
  47. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +36 -0
  48. data/lib/ddtrace/contrib/redis/integration.rb +7 -3
  49. data/lib/ddtrace/contrib/redis/patcher.rb +11 -2
  50. data/lib/ddtrace/contrib/redis/vendor/resolver.rb +159 -0
  51. data/lib/ddtrace/contrib/resque/integration.rb +8 -2
  52. data/lib/ddtrace/contrib/rest_client/integration.rb +6 -2
  53. data/lib/ddtrace/contrib/sequel/integration.rb +6 -2
  54. data/lib/ddtrace/contrib/shoryuken/integration.rb +9 -7
  55. data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +5 -0
  56. data/lib/ddtrace/contrib/sidekiq/ext.rb +2 -0
  57. data/lib/ddtrace/contrib/sidekiq/integration.rb +2 -2
  58. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +7 -3
  59. data/lib/ddtrace/contrib/sidekiq/tracing.rb +19 -2
  60. data/lib/ddtrace/contrib/sinatra/integration.rb +2 -2
  61. data/lib/ddtrace/contrib/sucker_punch/integration.rb +3 -3
  62. data/lib/ddtrace/runtime/metrics.rb +2 -2
  63. data/lib/ddtrace/sampling/rule_sampler.rb +16 -2
  64. data/lib/ddtrace/version.rb +1 -1
  65. metadata +12 -18
@@ -19,8 +19,8 @@ module Datadog
19
19
  Gem.loaded_specs['activerecord'] && Gem.loaded_specs['activerecord'].version
20
20
  end
21
21
 
22
- def self.present?
23
- super && defined?(::ActiveRecord)
22
+ def self.loaded?
23
+ defined?(::ActiveRecord)
24
24
  end
25
25
 
26
26
  def self.compatible?
@@ -17,8 +17,8 @@ module Datadog
17
17
  Gem.loaded_specs['activesupport'] && Gem.loaded_specs['activesupport'].version
18
18
  end
19
19
 
20
- def self.present?
21
- super && defined?(::ActiveSupport)
20
+ def self.loaded?
21
+ defined?(::ActiveSupport)
22
22
  end
23
23
 
24
24
  def self.compatible?
@@ -19,8 +19,12 @@ module Datadog
19
19
  end
20
20
  end
21
21
 
22
- def self.present?
23
- super && defined?(::Seahorse::Client::Base)
22
+ def self.loaded?
23
+ defined?(::Seahorse::Client::Base)
24
+ end
25
+
26
+ def self.compatible?
27
+ super && version >= Gem::Version.new('2.0')
24
28
  end
25
29
 
26
30
  def default_configuration
@@ -28,9 +28,15 @@ module Datadog
28
28
  end
29
29
 
30
30
  def loaded_constants
31
- SERVICES.each_with_object([]) do |service, constants|
31
+ # Cross-check services against loaded AWS constants
32
+ # Module#const_get can return a constant from ancestors when there's a miss.
33
+ # If this conincidentally matches another constant, it will attempt to patch
34
+ # the wrong constant, resulting in patch failure.
35
+ available_services = ::Aws.constants & SERVICES.map(&:to_sym)
36
+
37
+ available_services.each_with_object([]) do |service, constants|
32
38
  next if ::Aws.autoload?(service)
33
- constants << ::Aws.const_get(service).const_get(:Client) rescue next
39
+ constants << ::Aws.const_get(service, false).const_get(:Client, false) rescue next
34
40
  end
35
41
  end
36
42
 
@@ -15,8 +15,12 @@ module Datadog
15
15
  Gem.loaded_specs['concurrent-ruby'] && Gem.loaded_specs['concurrent-ruby'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Concurrent::Future)
18
+ def self.loaded?
19
+ defined?(::Concurrent::Future)
20
+ end
21
+
22
+ def self.compatible?
23
+ super && version >= Gem::Version.new('0.9')
20
24
  end
21
25
 
22
26
  def default_configuration
@@ -20,35 +20,52 @@ module Datadog
20
20
  @resolver = nil
21
21
  end
22
22
 
23
+ # Get matching configuration for key.
24
+ # If no match, returns default configuration.
23
25
  def configuration(key = :default)
24
- configurations[resolve_configuration_key(key)]
26
+ configurations[configuration_key(key)]
27
+ end
28
+
29
+ # If the key has matching configuration explicitly defined for it,
30
+ # then return true. Otherwise return false.
31
+ def configuration_for?(key)
32
+ key = resolver.resolve(key) unless key == :default
33
+ configurations.key?(key)
25
34
  end
26
35
 
27
36
  def configurations
28
- @configurations ||= Hash.new { default_configuration }.tap do |configs|
29
- configs[:default] = default_configuration
30
- end
37
+ @configurations ||= {
38
+ default: default_configuration
39
+ }
31
40
  end
32
41
 
42
+ # Create or update configuration with provided settings.
33
43
  def configure(key, options = {}, &block)
34
- key = resolver.resolve(key || :default)
44
+ key ||= :default
35
45
 
36
- configurations[key].tap do |settings|
37
- settings.configure(options, &block)
38
- configurations[key] = settings
39
- end
46
+ # Get or add the configuration
47
+ config = configuration_for?(key) ? configuration(key) : add_configuration(key)
48
+
49
+ # Apply the settings
50
+ config.configure(options, &block)
51
+ config
40
52
  end
41
53
 
42
54
  protected
43
55
 
44
- attr_writer :resolver
45
-
46
56
  def resolver
47
57
  @resolver ||= Configuration::Resolver.new
48
58
  end
49
59
 
50
- def resolve_configuration_key(key = :default)
51
- key = :default if key.nil?
60
+ def add_configuration(key)
61
+ resolver.add(key)
62
+ config_key = resolver.resolve(key)
63
+ configurations[config_key] = default_configuration
64
+ end
65
+
66
+ def configuration_key(key)
67
+ return :default if key.nil? || key == :default
68
+
52
69
  key = resolver.resolve(key)
53
70
  key = :default unless configurations.key?(key)
54
71
  key
@@ -1,10 +1,14 @@
1
1
  module Datadog
2
2
  module Contrib
3
3
  module Configuration
4
- # Resolves a value to a configuration key
4
+ # Resolves a configuration key to a Datadog::Contrib::Configuration:Settings object
5
5
  class Resolver
6
- def resolve(name)
7
- name
6
+ def resolve(key)
7
+ key
8
+ end
9
+
10
+ def add(key)
11
+ key
8
12
  end
9
13
  end
10
14
  end
@@ -15,8 +15,8 @@ module Datadog
15
15
  Gem.loaded_specs['dalli'] && Gem.loaded_specs['dalli'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Dalli)
18
+ def self.loaded?
19
+ defined?(::Dalli)
20
20
  end
21
21
 
22
22
  def self.compatible?
@@ -15,8 +15,12 @@ module Datadog
15
15
  Gem.loaded_specs['delayed_job'] && Gem.loaded_specs['delayed_job'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Delayed)
18
+ def self.loaded?
19
+ defined?(::Delayed)
20
+ end
21
+
22
+ def self.compatible?
23
+ super && version >= Gem::Version.new('4.1')
20
24
  end
21
25
 
22
26
  def default_configuration
@@ -16,8 +16,8 @@ module Datadog
16
16
  && Gem.loaded_specs['elasticsearch-transport'].version
17
17
  end
18
18
 
19
- def self.present?
20
- super && defined?(::Elasticsearch::Transport)
19
+ def self.loaded?
20
+ defined?(::Elasticsearch::Transport)
21
21
  end
22
22
 
23
23
  def self.compatible?
@@ -14,8 +14,12 @@ module Datadog
14
14
  Gem.loaded_specs['ethon'] && Gem.loaded_specs['ethon'].version
15
15
  end
16
16
 
17
- def self.present?
18
- super && defined?(::Ethon::Easy)
17
+ def self.loaded?
18
+ defined?(::Ethon::Easy)
19
+ end
20
+
21
+ def self.compatible?
22
+ super && version >= Gem::Version.new('0.11.0')
19
23
  end
20
24
 
21
25
  def default_configuration
@@ -15,8 +15,12 @@ module Datadog
15
15
  Gem.loaded_specs['excon'] && Gem.loaded_specs['excon'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Excon)
18
+ def self.loaded?
19
+ defined?(::Excon)
20
+ end
21
+
22
+ def self.compatible?
23
+ super && version >= Gem::Version.new('0.62')
20
24
  end
21
25
 
22
26
  def default_configuration
@@ -15,8 +15,8 @@ module Datadog
15
15
  Gem.loaded_specs['faraday'] && Gem.loaded_specs['faraday'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Faraday)
18
+ def self.loaded?
19
+ defined?(::Faraday)
20
20
  end
21
21
 
22
22
  def self.compatible?
@@ -15,12 +15,12 @@ module Datadog
15
15
  Gem.loaded_specs['grape'] && Gem.loaded_specs['grape'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Grape)
18
+ def self.loaded?
19
+ defined?(::Grape) && defined?(::ActiveSupport::Notifications)
20
20
  end
21
21
 
22
22
  def self.compatible?
23
- super && defined?(::ActiveSupport::Notifications)
23
+ super && version >= Gem::Version.new('1.0')
24
24
  end
25
25
 
26
26
  def default_configuration
@@ -15,14 +15,12 @@ module Datadog
15
15
  Gem.loaded_specs['graphql'] && Gem.loaded_specs['graphql'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::GraphQL)
18
+ def self.loaded?
19
+ defined?(::GraphQL) && defined?(::GraphQL::Tracing::DataDogTracing)
20
20
  end
21
21
 
22
22
  def self.compatible?
23
- super \
24
- && defined?(::GraphQL::Tracing::DataDogTracing) \
25
- && version >= Gem::Version.new('1.7.9')
23
+ super && version >= Gem::Version.new('1.7.9')
26
24
  end
27
25
 
28
26
  def default_configuration
@@ -15,8 +15,8 @@ module Datadog
15
15
  Gem.loaded_specs['grpc'] && Gem.loaded_specs['grpc'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::GRPC)
18
+ def self.loaded?
19
+ defined?(::GRPC)
20
20
  end
21
21
 
22
22
  def self.compatible?
@@ -19,6 +19,10 @@ module Datadog
19
19
  Gem::Version.new(RUBY_VERSION)
20
20
  end
21
21
 
22
+ def self.loaded?
23
+ defined?(::Net::HTTP)
24
+ end
25
+
22
26
  def default_configuration
23
27
  Configuration::Settings.new
24
28
  end
@@ -15,8 +15,8 @@ module Datadog
15
15
  Gem.loaded_specs['mongo'] && Gem.loaded_specs['mongo'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Mongo::Monitoring::Global)
18
+ def self.loaded?
19
+ defined?(::Mongo::Monitoring::Global)
20
20
  end
21
21
 
22
22
  def self.compatible?
@@ -15,8 +15,12 @@ module Datadog
15
15
  Gem.loaded_specs['mysql2'] && Gem.loaded_specs['mysql2'].version
16
16
  end
17
17
 
18
- def self.present?
19
- super && defined?(::Mysql2)
18
+ def self.loaded?
19
+ defined?(::Mysql2)
20
+ end
21
+
22
+ def self.compatible?
23
+ super && version >= Gem::Version.new('0.3.21')
20
24
  end
21
25
 
22
26
  def default_configuration
@@ -13,12 +13,24 @@ module Datadog
13
13
  nil
14
14
  end
15
15
 
16
- def present?
16
+ # Is the target available? (e.g. gem installed?)
17
+ def available?
17
18
  !version.nil?
18
19
  end
19
20
 
21
+ # Is the target loaded into the application? (e.g. constants defined?)
22
+ def loaded?
23
+ true
24
+ end
25
+
26
+ # Is the loaded code compatible with this integration? (e.g. minimum version met?)
20
27
  def compatible?
21
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new(VERSION::MINIMUM_RUBY_VERSION) && present?
28
+ Gem::Version.new(RUBY_VERSION) >= Gem::Version.new(VERSION::MINIMUM_RUBY_VERSION)
29
+ end
30
+
31
+ # Can the patch for this integration be applied?
32
+ def patchable?
33
+ available? && loaded? && compatible?
22
34
  end
23
35
  end
24
36
 
@@ -29,8 +41,13 @@ module Datadog
29
41
  end
30
42
 
31
43
  def patch
32
- if !self.class.compatible? || patcher.nil?
33
- Datadog::Logger.log.warn("Unable to patch #{self.class.name}")
44
+ if !self.class.patchable? || patcher.nil?
45
+ desc = "Available?: #{self.class.available?}"
46
+ desc += ", Loaded? #{self.class.loaded?}"
47
+ desc += ", Compatible? #{self.class.compatible?}"
48
+ desc += ", Patchable? #{self.class.patchable?}"
49
+
50
+ Datadog::Logger.log.warn("Unable to patch #{self.class.name} (#{desc})")
34
51
  return
35
52
  end
36
53
 
@@ -0,0 +1,23 @@
1
+ require 'ddtrace/contrib/configuration/settings'
2
+ require 'ddtrace/contrib/presto/ext'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module Presto
7
+ module Configuration
8
+ # Custom settings for the Presto 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 :service_name, default: Ext::SERVICE_NAME
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Presto
4
+ # Presto integration constants
5
+ module Ext
6
+ APP = 'presto'.freeze
7
+ ENV_ANALYTICS_ENABLED = 'DD_PRESTO_ANALYTICS_ENABLED'.freeze
8
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_PRESTO_ANALYTICS_SAMPLE_RATE'.freeze
9
+ SERVICE_NAME = 'presto'.freeze
10
+ SPAN_QUERY = 'presto.query'.freeze
11
+ SPAN_RESUME = 'presto.resume_query'.freeze
12
+ SPAN_KILL = 'presto.kill_query'.freeze
13
+ TAG_SCHEMA_NAME = 'presto.schema'.freeze
14
+ TAG_CATALOG_NAME = 'presto.catalog'.freeze
15
+ TAG_USER_NAME = 'presto.user'.freeze
16
+ TAG_TIME_ZONE = 'presto.time_zone'.freeze
17
+ TAG_LANGUAGE = 'presto.language'.freeze
18
+ TAG_PROXY = 'presto.http_proxy'.freeze
19
+ TAG_MODEL_VERSION = 'presto.model_version'.freeze
20
+ TAG_QUERY_ID = 'presto.query.id'.freeze
21
+ TAG_QUERY_ASYNC = 'presto.query.async'.freeze
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,107 @@
1
+ require 'ddtrace/ext/net'
2
+ require 'ddtrace/ext/sql'
3
+ require 'ddtrace/ext/app_types'
4
+ require 'ddtrace/contrib/presto/ext'
5
+
6
+ module Datadog
7
+ module Contrib
8
+ module Presto
9
+ # Instrumentation for Presto integration
10
+ module Instrumentation
11
+ # Instrumentation for Presto::Client::Client
12
+ module Client
13
+ def self.included(base)
14
+ base.send(:prepend, InstanceMethods)
15
+ end
16
+
17
+ # Instance methods for Presto::Client
18
+ module InstanceMethods
19
+ def run(query)
20
+ tracer.trace(Ext::SPAN_QUERY, span_options) do |span|
21
+ begin
22
+ decorate!(span)
23
+ span.resource = query
24
+ span.span_type = Datadog::Ext::SQL::TYPE
25
+ span.set_tag(Ext::TAG_QUERY_ASYNC, false)
26
+ rescue StandardError => e
27
+ Datadog::Logger.log.debug("error preparing span for presto: #{e}")
28
+ ensure
29
+ super(query)
30
+ end
31
+ end
32
+ end
33
+
34
+ def query(query, &blk)
35
+ tracer.trace(Ext::SPAN_QUERY, span_options) do |span|
36
+ begin
37
+ decorate!(span)
38
+ span.resource = query
39
+ span.span_type = Datadog::Ext::SQL::TYPE
40
+ span.set_tag(Ext::TAG_QUERY_ASYNC, !blk.nil?)
41
+ rescue StandardError => e
42
+ Datadog::Logger.log.debug("error preparing span for presto: #{e}")
43
+ ensure
44
+ super(query, &blk)
45
+ end
46
+ end
47
+ end
48
+
49
+ def kill(query_id)
50
+ tracer.trace(Ext::SPAN_KILL, span_options) do |span|
51
+ begin
52
+ decorate!(span)
53
+ span.resource = Ext::SPAN_KILL
54
+ span.span_type = Datadog::Ext::AppTypes::DB
55
+ # ^ not an SQL type span, since there's no SQL query
56
+ span.set_tag(Ext::TAG_QUERY_ID, query_id)
57
+ rescue StandardError => e
58
+ Datadog::Logger.log.debug("error preparing span for presto: #{e}")
59
+ ensure
60
+ super(query_id)
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def datadog_configuration
68
+ Datadog.configuration[:presto]
69
+ end
70
+
71
+ def span_options
72
+ {
73
+ service: datadog_configuration[:service_name],
74
+ app: Ext::APP,
75
+ app_type: Datadog::Ext::AppTypes::DB
76
+ }
77
+ end
78
+
79
+ def tracer
80
+ datadog_configuration.tracer
81
+ end
82
+
83
+ def decorate!(span)
84
+ set_nilable_tag!(span, :server, Datadog::Ext::NET::TARGET_HOST)
85
+ set_nilable_tag!(span, :user, Ext::TAG_USER_NAME)
86
+ set_nilable_tag!(span, :schema, Ext::TAG_SCHEMA_NAME)
87
+ set_nilable_tag!(span, :catalog, Ext::TAG_CATALOG_NAME)
88
+ set_nilable_tag!(span, :time_zone, Ext::TAG_TIME_ZONE)
89
+ set_nilable_tag!(span, :language, Ext::TAG_LANGUAGE)
90
+ set_nilable_tag!(span, :http_proxy, Ext::TAG_PROXY)
91
+ set_nilable_tag!(span, :model_version, Ext::TAG_MODEL_VERSION)
92
+
93
+ # Set analytics sample rate
94
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
95
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
96
+ end
97
+ end
98
+
99
+ def set_nilable_tag!(span, key, tag_name)
100
+ @options[key].tap { |val| span.set_tag(tag_name, val) if val }
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end