ddtrace 0.13.2 → 0.14.0.beta1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -0
  3. data/Appraisals +12 -0
  4. data/CHANGELOG.md +16 -5
  5. data/Rakefile +18 -1
  6. data/docs/GettingStarted.md +63 -0
  7. data/lib/ddtrace.rb +3 -1
  8. data/lib/ddtrace/configuration.rb +18 -6
  9. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +46 -0
  10. data/lib/ddtrace/contrib/active_record/configuration/settings.rb +28 -0
  11. data/lib/ddtrace/contrib/active_record/events/sql.rb +11 -7
  12. data/lib/ddtrace/contrib/active_record/integration.rb +44 -0
  13. data/lib/ddtrace/contrib/active_record/patcher.rb +4 -28
  14. data/lib/ddtrace/contrib/active_record/utils.rb +5 -11
  15. data/lib/ddtrace/contrib/base.rb +4 -3
  16. data/lib/ddtrace/contrib/configurable.rb +55 -0
  17. data/lib/ddtrace/contrib/configuration/option.rb +33 -0
  18. data/lib/ddtrace/contrib/configuration/option_definition.rb +29 -0
  19. data/lib/ddtrace/contrib/configuration/option_definition_set.rb +20 -0
  20. data/lib/ddtrace/contrib/configuration/option_set.rb +8 -0
  21. data/lib/ddtrace/contrib/configuration/options.rb +95 -0
  22. data/lib/ddtrace/contrib/configuration/resolver.rb +12 -0
  23. data/lib/ddtrace/contrib/configuration/settings.rb +35 -0
  24. data/lib/ddtrace/contrib/delayed_job/patcher.rb +41 -0
  25. data/lib/ddtrace/contrib/delayed_job/plugin.rb +43 -0
  26. data/lib/ddtrace/contrib/integration.rb +16 -0
  27. data/lib/ddtrace/contrib/patchable.rb +38 -0
  28. data/lib/ddtrace/contrib/patcher.rb +28 -0
  29. data/lib/ddtrace/contrib/rake/instrumentation.rb +3 -15
  30. data/lib/ddtrace/contrib/registerable.rb +33 -0
  31. data/lib/ddtrace/contrib/resque/resque_job.rb +2 -10
  32. data/lib/ddtrace/contrib/sequel/configuration/settings.rb +13 -0
  33. data/lib/ddtrace/contrib/sequel/database.rb +1 -1
  34. data/lib/ddtrace/contrib/sequel/integration.rb +38 -0
  35. data/lib/ddtrace/contrib/sequel/patcher.rb +4 -20
  36. data/lib/ddtrace/patcher.rb +5 -0
  37. data/lib/ddtrace/propagation/http_propagator.rb +0 -6
  38. data/lib/ddtrace/tracer.rb +17 -5
  39. data/lib/ddtrace/vendor/active_record/connection_specification.rb +301 -0
  40. data/lib/ddtrace/version.rb +3 -3
  41. metadata +24 -4
@@ -22,9 +22,13 @@ module Datadog
22
22
  end
23
23
 
24
24
  def process(span, event, _id, payload)
25
- connection_config = Utils.connection_config(payload[:connection_id])
26
- span.name = "#{connection_config[:adapter_name]}.query"
27
- span.service = configuration[:service_name]
25
+ config = Utils.connection_config(payload[:connection_id])
26
+ settings = Datadog.configuration[:active_record, config]
27
+ adapter_name = Datadog::Utils::Database.normalize_vendor(config[:adapter])
28
+ service_name = !settings.nil? ? settings.service_name : configuration[:service_name]
29
+
30
+ span.name = "#{adapter_name}.query"
31
+ span.service = service_name
28
32
  span.resource = payload.fetch(:sql)
29
33
  span.span_type = Datadog::Ext::SQL::TYPE
30
34
 
@@ -33,11 +37,11 @@ module Datadog
33
37
  # is simply cached from memory, so the notification is fired with start == finish.
34
38
  cached = payload[:cached] || (payload[:name] == 'CACHE')
35
39
 
36
- span.set_tag('active_record.db.vendor', connection_config[:adapter_name])
37
- span.set_tag('active_record.db.name', connection_config[:database_name])
40
+ span.set_tag('active_record.db.vendor', adapter_name)
41
+ span.set_tag('active_record.db.name', config[:database])
38
42
  span.set_tag('active_record.db.cached', cached) if cached
39
- span.set_tag('out.host', connection_config[:adapter_host])
40
- span.set_tag('out.port', connection_config[:adapter_port])
43
+ span.set_tag('out.host', config[:host]) if config[:host]
44
+ span.set_tag('out.port', config[:port]) if config[:port]
41
45
  rescue StandardError => e
42
46
  Datadog::Tracer.log.debug(e.message)
43
47
  end
@@ -0,0 +1,44 @@
1
+ require 'ddtrace/ext/sql'
2
+ require 'ddtrace/ext/app_types'
3
+ require 'ddtrace/contrib/integration'
4
+ require 'ddtrace/contrib/active_record/events'
5
+ require 'ddtrace/contrib/active_record/configuration/resolver'
6
+ require 'ddtrace/contrib/active_record/configuration/settings'
7
+ require 'ddtrace/contrib/active_record/patcher'
8
+
9
+ module Datadog
10
+ module Contrib
11
+ module ActiveRecord
12
+ # Describes the ActiveRecord integration
13
+ class Integration
14
+ include Contrib::Integration
15
+
16
+ register_as :active_record, auto_patch: false
17
+
18
+ def self.version
19
+ Gem.loaded_specs['activerecord'] && Gem.loaded_specs['activerecord'].version
20
+ end
21
+
22
+ def self.present?
23
+ super && defined?(::ActiveRecord)
24
+ end
25
+
26
+ def self.compatible?
27
+ super && version >= Gem::Version.new('3.0')
28
+ end
29
+
30
+ def default_configuration
31
+ Configuration::Settings.new
32
+ end
33
+
34
+ def patcher
35
+ ActiveRecord::Patcher
36
+ end
37
+
38
+ def resolver
39
+ @resolver ||= Configuration::Resolver.new
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,6 +1,4 @@
1
- require 'ddtrace/ext/sql'
2
- require 'ddtrace/ext/app_types'
3
- require 'ddtrace/contrib/active_record/utils'
1
+ require 'ddtrace/contrib/patcher'
4
2
  require 'ddtrace/contrib/active_record/events'
5
3
 
6
4
  module Datadog
@@ -8,44 +6,22 @@ module Datadog
8
6
  module ActiveRecord
9
7
  # Patcher enables patching of 'active_record' module.
10
8
  module Patcher
11
- include Base
12
-
13
- register_as :active_record, auto_patch: false
14
- option :service_name, depends_on: [:tracer] do |value|
15
- (value || Utils.adapter_name).tap do |v|
16
- get_option(:tracer).set_service_info(v, 'active_record', Ext::AppTypes::DB)
17
- end
18
- end
19
- option :orm_service_name
20
- option :tracer, default: Datadog.tracer do |value|
21
- (value || Datadog.tracer).tap do |v|
22
- # Make sure to update tracers of all subscriptions
23
- Events.subscriptions.each do |subscription|
24
- subscription.tracer = v
25
- end
26
- end
27
- end
28
-
29
- @patched = false
9
+ include Contrib::Patcher
30
10
 
31
11
  module_function
32
12
 
33
- # patched? tells whether patch has been successfully applied
34
13
  def patched?
35
- @patched
14
+ done?(:active_record)
36
15
  end
37
16
 
38
17
  def patch
39
- if !@patched && defined?(::ActiveRecord)
18
+ do_once(:active_record) do
40
19
  begin
41
20
  Events.subscribe!
42
- @patched = true
43
21
  rescue StandardError => e
44
22
  Datadog::Tracer.log.error("Unable to apply Active Record integration: #{e}")
45
23
  end
46
24
  end
47
-
48
- @patched
49
25
  end
50
26
  end
51
27
  end
@@ -4,29 +4,23 @@ module Datadog
4
4
  # Common utilities for Rails
5
5
  module Utils
6
6
  def self.adapter_name
7
- connection_config[:adapter_name]
7
+ Datadog::Utils::Database.normalize_vendor(connection_config[:adapter])
8
8
  end
9
9
 
10
10
  def self.database_name
11
- connection_config[:database_name]
11
+ connection_config[:database]
12
12
  end
13
13
 
14
14
  def self.adapter_host
15
- connection_config[:adapter_host]
15
+ connection_config[:host]
16
16
  end
17
17
 
18
18
  def self.adapter_port
19
- connection_config[:adapter_port]
19
+ connection_config[:port]
20
20
  end
21
21
 
22
22
  def self.connection_config(object_id = nil)
23
- config = object_id.nil? ? default_connection_config : connection_config_by_id(object_id)
24
- {
25
- adapter_name: Datadog::Utils::Database.normalize_vendor(config[:adapter]),
26
- adapter_host: config[:host],
27
- adapter_port: config[:port],
28
- database_name: config[:database]
29
- }
23
+ object_id.nil? ? default_connection_config : connection_config_by_id(object_id)
30
24
  end
31
25
 
32
26
  # Attempt to retrieve the connection from an object ID.
@@ -1,5 +1,6 @@
1
- require 'ddtrace/registry'
2
1
  require 'ddtrace/configurable'
2
+ require 'ddtrace/patcher'
3
+ require 'ddtrace/registry/registerable'
3
4
 
4
5
  module Datadog
5
6
  module Contrib
@@ -7,8 +8,8 @@ module Datadog
7
8
  module Base
8
9
  def self.included(base)
9
10
  base.send(:include, Registry::Registerable)
10
- base.send(:include, Configurable)
11
- base.send(:include, Patcher)
11
+ base.send(:include, Datadog::Configurable)
12
+ base.send(:include, Datadog::Patcher)
12
13
  end
13
14
  end
14
15
  end
@@ -0,0 +1,55 @@
1
+ require 'ddtrace/contrib/configuration/resolver'
2
+ require 'ddtrace/contrib/configuration/settings'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ # Defines configurable behavior for integrations
7
+ module Configurable
8
+ def self.included(base)
9
+ base.send(:include, InstanceMethods)
10
+ end
11
+
12
+ # Configurable instance behavior for integrations
13
+ module InstanceMethods
14
+ def default_configuration
15
+ Configuration::Settings.new
16
+ end
17
+
18
+ def reset_configuration!
19
+ @configurations = nil
20
+ @resolver = nil
21
+ end
22
+
23
+ def configuration(name = :default)
24
+ name = :default if name.nil?
25
+ name = resolver.resolve(name)
26
+ return nil unless configurations.key?(name)
27
+ configurations[name]
28
+ end
29
+
30
+ def configurations
31
+ @configurations ||= Hash.new { default_configuration }.tap do |configs|
32
+ configs[:default] = default_configuration
33
+ end
34
+ end
35
+
36
+ def configure(name, options = {}, &block)
37
+ name = resolver.resolve(name || :default)
38
+
39
+ configurations[name].tap do |settings|
40
+ settings.configure(options, &block)
41
+ configurations[name] = settings
42
+ end
43
+ end
44
+
45
+ protected
46
+
47
+ attr_writer :resolver
48
+
49
+ def resolver
50
+ @resolver ||= Configuration::Resolver.new
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,33 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Configuration
4
+ # Represents an instance of an integration configuration option
5
+ class Option
6
+ attr_reader \
7
+ :definition
8
+
9
+ def initialize(definition, context)
10
+ @definition = definition
11
+ @context = context
12
+ @value = nil
13
+ @is_set = false
14
+ end
15
+
16
+ def set(value)
17
+ @value = @context.instance_exec(value, &definition.setter).tap do
18
+ @is_set = true
19
+ end
20
+ end
21
+
22
+ def get
23
+ return definition.default_value unless @is_set
24
+ @value
25
+ end
26
+
27
+ def reset
28
+ set(definition.default_value)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Configuration
4
+ # Represents a definition for an integration configuration option
5
+ class OptionDefinition
6
+ IDENTITY = ->(x) { x }
7
+
8
+ attr_reader \
9
+ :default,
10
+ :depends_on,
11
+ :lazy,
12
+ :name,
13
+ :setter
14
+
15
+ def initialize(name, meta = {}, &block)
16
+ @default = meta[:default]
17
+ @depends_on = meta[:depends_on] || []
18
+ @lazy = meta[:lazy] || false
19
+ @name = name.to_sym
20
+ @setter = meta[:setter] || block || IDENTITY
21
+ end
22
+
23
+ def default_value
24
+ lazy ? @default.call : @default
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ require 'ddtrace/configuration/resolver'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module Configuration
6
+ # Represents a set of configuration option definitions for an integration
7
+ class OptionDefinitionSet < Hash
8
+ def dependency_order
9
+ Datadog::Configuration::Resolver.new(dependency_graph).call
10
+ end
11
+
12
+ def dependency_graph
13
+ each_with_object({}) do |(name, option), graph|
14
+ graph[name] = option.depends_on
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Configuration
4
+ class OptionSet < Hash
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,95 @@
1
+ require 'ddtrace/contrib/configuration/option'
2
+ require 'ddtrace/contrib/configuration/option_set'
3
+ require 'ddtrace/contrib/configuration/option_definition'
4
+ require 'ddtrace/contrib/configuration/option_definition_set'
5
+
6
+ module Datadog
7
+ module Contrib
8
+ module Configuration
9
+ # Behavior for a configuration object that has options
10
+ module Options
11
+ def self.included(base)
12
+ base.send(:extend, ClassMethods)
13
+ base.send(:include, InstanceMethods)
14
+ end
15
+
16
+ # Class behavior for a configuration object with options
17
+ module ClassMethods
18
+ def options
19
+ @options ||= begin
20
+ # Allows for class inheritance of option definitions
21
+ superclass <= Options ? superclass.options.dup : OptionDefinitionSet.new
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def option(name, meta = {}, &block)
28
+ options[name] = OptionDefinition.new(name, meta, &block).tap do
29
+ define_option_accessors(name)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def define_option_accessors(name)
36
+ option_name = name
37
+
38
+ define_method(option_name) do
39
+ get_option(option_name)
40
+ end
41
+
42
+ define_method("#{option_name}=") do |value|
43
+ set_option(option_name, value)
44
+ end
45
+ end
46
+ end
47
+
48
+ # Instance behavior for a configuration object with options
49
+ module InstanceMethods
50
+ def options
51
+ @options ||= OptionSet.new
52
+ end
53
+
54
+ def set_option(name, value)
55
+ add_option(name) unless options.key?(name)
56
+ options[name].set(value)
57
+ end
58
+
59
+ def get_option(name)
60
+ add_option(name) unless options.key?(name)
61
+ options[name].get
62
+ end
63
+
64
+ def to_h
65
+ options.each_with_object({}) do |(key, _), hash|
66
+ hash[key] = get_option(key)
67
+ end
68
+ end
69
+
70
+ def reset_options!
71
+ options.values.each(&:reset)
72
+ end
73
+
74
+ private
75
+
76
+ def add_option(name)
77
+ assert_valid_option!(name)
78
+ definition = self.class.options[name]
79
+ Option.new(definition, self).tap do |option|
80
+ options[name] = option
81
+ end
82
+ end
83
+
84
+ def assert_valid_option!(name)
85
+ unless self.class.options.key?(name)
86
+ raise(InvalidOptionError, "#{self.class.name} doesn't define the option: #{name}")
87
+ end
88
+ end
89
+ end
90
+
91
+ InvalidOptionError = Class.new(StandardError)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,12 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Configuration
4
+ # Resolves a value to a configuration key
5
+ class Resolver
6
+ def resolve(name)
7
+ name
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end