ddtrace 0.13.2 → 0.14.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/Appraisals +12 -0
- data/CHANGELOG.md +16 -5
- data/Rakefile +18 -1
- data/docs/GettingStarted.md +63 -0
- data/lib/ddtrace.rb +3 -1
- data/lib/ddtrace/configuration.rb +18 -6
- data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +46 -0
- data/lib/ddtrace/contrib/active_record/configuration/settings.rb +28 -0
- data/lib/ddtrace/contrib/active_record/events/sql.rb +11 -7
- data/lib/ddtrace/contrib/active_record/integration.rb +44 -0
- data/lib/ddtrace/contrib/active_record/patcher.rb +4 -28
- data/lib/ddtrace/contrib/active_record/utils.rb +5 -11
- data/lib/ddtrace/contrib/base.rb +4 -3
- data/lib/ddtrace/contrib/configurable.rb +55 -0
- data/lib/ddtrace/contrib/configuration/option.rb +33 -0
- data/lib/ddtrace/contrib/configuration/option_definition.rb +29 -0
- data/lib/ddtrace/contrib/configuration/option_definition_set.rb +20 -0
- data/lib/ddtrace/contrib/configuration/option_set.rb +8 -0
- data/lib/ddtrace/contrib/configuration/options.rb +95 -0
- data/lib/ddtrace/contrib/configuration/resolver.rb +12 -0
- data/lib/ddtrace/contrib/configuration/settings.rb +35 -0
- data/lib/ddtrace/contrib/delayed_job/patcher.rb +41 -0
- data/lib/ddtrace/contrib/delayed_job/plugin.rb +43 -0
- data/lib/ddtrace/contrib/integration.rb +16 -0
- data/lib/ddtrace/contrib/patchable.rb +38 -0
- data/lib/ddtrace/contrib/patcher.rb +28 -0
- data/lib/ddtrace/contrib/rake/instrumentation.rb +3 -15
- data/lib/ddtrace/contrib/registerable.rb +33 -0
- data/lib/ddtrace/contrib/resque/resque_job.rb +2 -10
- data/lib/ddtrace/contrib/sequel/configuration/settings.rb +13 -0
- data/lib/ddtrace/contrib/sequel/database.rb +1 -1
- data/lib/ddtrace/contrib/sequel/integration.rb +38 -0
- data/lib/ddtrace/contrib/sequel/patcher.rb +4 -20
- data/lib/ddtrace/patcher.rb +5 -0
- data/lib/ddtrace/propagation/http_propagator.rb +0 -6
- data/lib/ddtrace/tracer.rb +17 -5
- data/lib/ddtrace/vendor/active_record/connection_specification.rb +301 -0
- data/lib/ddtrace/version.rb +3 -3
- metadata +24 -4
@@ -22,9 +22,13 @@ module Datadog
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def process(span, event, _id, payload)
|
25
|
-
|
26
|
-
|
27
|
-
|
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',
|
37
|
-
span.set_tag('active_record.db.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',
|
40
|
-
span.set_tag('out.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/
|
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
|
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
|
-
|
14
|
+
done?(:active_record)
|
36
15
|
end
|
37
16
|
|
38
17
|
def patch
|
39
|
-
|
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[:
|
7
|
+
Datadog::Utils::Database.normalize_vendor(connection_config[:adapter])
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.database_name
|
11
|
-
connection_config[:
|
11
|
+
connection_config[:database]
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.adapter_host
|
15
|
-
connection_config[:
|
15
|
+
connection_config[:host]
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.adapter_port
|
19
|
-
connection_config[:
|
19
|
+
connection_config[:port]
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.connection_config(object_id = nil)
|
23
|
-
|
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.
|
data/lib/ddtrace/contrib/base.rb
CHANGED
@@ -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,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
|