ddtrace 0.32.0 → 0.33.0

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