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
@@ -0,0 +1,35 @@
1
+ require 'ddtrace/contrib/configuration/options'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module Configuration
6
+ # Common settings for all integrations
7
+ class Settings
8
+ include Options
9
+
10
+ option :service_name
11
+ option :tracer, default: Datadog.tracer
12
+
13
+ def initialize(options = {})
14
+ configure(options)
15
+ end
16
+
17
+ def configure(options = {})
18
+ self.class.options.dependency_order.each do |name|
19
+ self[name] = options.fetch(name, self[name])
20
+ end
21
+
22
+ yield(self) if block_given?
23
+ end
24
+
25
+ def [](name)
26
+ respond_to?(name) ? send(name) : get_option(name)
27
+ end
28
+
29
+ def []=(name, value)
30
+ respond_to?("#{name}=") ? send("#{name}=", value) : set_option(name, value)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ module Datadog
2
+ module Contrib
3
+ module DelayedJob
4
+ # DelayedJob integration
5
+ module Patcher
6
+ include Base
7
+ register_as :delayed_job
8
+
9
+ option :service_name, default: 'delayed_job'.freeze
10
+ option :tracer, default: Datadog.tracer
11
+
12
+ @patched = false
13
+
14
+ class << self
15
+ def patch
16
+ return @patched if patched? || !defined?(::Delayed)
17
+
18
+ require 'ddtrace/ext/app_types'
19
+ require_relative 'plugin'
20
+
21
+ add_instrumentation(::Delayed::Worker)
22
+ @patched = true
23
+ rescue => e
24
+ Tracer.log.error("Unable to apply DelayedJob integration: #{e}")
25
+ @patched
26
+ end
27
+
28
+ def patched?
29
+ @patched
30
+ end
31
+
32
+ private
33
+
34
+ def add_instrumentation(klass)
35
+ klass.plugins << Plugin
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,43 @@
1
+ require 'delayed/plugin'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module DelayedJob
6
+ # DelayedJob plugin that instruments invoke_job hook
7
+ class Plugin < Delayed::Plugin
8
+ def self.instrument(job, &block)
9
+ return block.call(job) unless tracer && tracer.enabled
10
+
11
+ tracer.trace('delayed_job'.freeze, service: configuration[:service_name], resource: job.name) do |span|
12
+ span.set_tag('delayed_job.id'.freeze, job.id)
13
+ span.set_tag('delayed_job.queue'.freeze, job.queue) if job.queue
14
+ span.set_tag('delayed_job.priority'.freeze, job.priority)
15
+ span.set_tag('delayed_job.attempts'.freeze, job.attempts)
16
+ span.span_type = Ext::AppTypes::WORKER
17
+
18
+ yield job
19
+ end
20
+ end
21
+
22
+ def self.flush(worker, &block)
23
+ yield worker
24
+
25
+ tracer.shutdown! if tracer && tracer.enabled
26
+ end
27
+
28
+ def self.configuration
29
+ Datadog.configuration[:delayed_job]
30
+ end
31
+
32
+ def self.tracer
33
+ configuration[:tracer]
34
+ end
35
+
36
+ callbacks do |lifecycle|
37
+ lifecycle.around(:invoke_job, &method(:instrument))
38
+ lifecycle.around(:execute, &method(:flush))
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,16 @@
1
+ require 'ddtrace/contrib/configurable'
2
+ require 'ddtrace/contrib/patchable'
3
+ require 'ddtrace/contrib/registerable'
4
+
5
+ module Datadog
6
+ module Contrib
7
+ # Base provides features that are shared across all integrations
8
+ module Integration
9
+ def self.included(base)
10
+ base.send(:include, Configurable)
11
+ base.send(:include, Patchable)
12
+ base.send(:include, Registerable)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ module Datadog
2
+ module Contrib
3
+ # Base provides features that are shared across all integrations
4
+ module Patchable
5
+ def self.included(base)
6
+ base.send(:extend, ClassMethods)
7
+ base.send(:include, InstanceMethods)
8
+ end
9
+
10
+ # Class methods for integrations
11
+ module ClassMethods
12
+ def version
13
+ nil
14
+ end
15
+
16
+ def present?
17
+ !version.nil?
18
+ end
19
+
20
+ def compatible?
21
+ RUBY_VERSION >= '1.9.3' && present?
22
+ end
23
+ end
24
+
25
+ # Instance methods for integrations
26
+ module InstanceMethods
27
+ def patcher
28
+ nil
29
+ end
30
+
31
+ def patch
32
+ return if !self.class.compatible? || patcher.nil?
33
+ patcher.patch
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ require 'ddtrace/patcher'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ # Common behavior for patcher modules
6
+ module Patcher
7
+ def self.included(base)
8
+ base.send(:include, Datadog::Patcher)
9
+ base.send(:extend, InstanceMethods)
10
+ base.send(:include, InstanceMethods)
11
+ end
12
+
13
+ # Class methods for patchers
14
+ module ClassMethods
15
+ def patch
16
+ raise NotImplementedError, '#patch not implemented for Patcher!'
17
+ end
18
+ end
19
+
20
+ # Instance methods for patchers
21
+ module InstanceMethods
22
+ def patch
23
+ raise NotImplementedError, '#patch not implemented for Patcher!'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -15,31 +15,23 @@ module Datadog
15
15
  def invoke(*args)
16
16
  return super unless enabled?
17
17
 
18
- tracer.trace(SPAN_NAME_INVOKE, span_options) do |span|
18
+ tracer.trace(SPAN_NAME_INVOKE) do |span|
19
19
  super
20
20
  annotate_invoke!(span, args)
21
21
  end
22
- ensure
23
- shutdown_tracer!
24
22
  end
25
23
 
26
24
  def execute(args = nil)
27
25
  return super unless enabled?
28
26
 
29
- tracer.trace(SPAN_NAME_EXECUTE, span_options) do |span|
27
+ tracer.trace(SPAN_NAME_EXECUTE) do |span|
30
28
  super
31
29
  annotate_execute!(span, args)
32
30
  end
33
- ensure
34
- shutdown_tracer!
35
31
  end
36
32
 
37
33
  private
38
34
 
39
- def shutdown_tracer!
40
- tracer.shutdown! if tracer.active_span.nil? && ::Rake.application.top_level_tasks.include?(name)
41
- end
42
-
43
35
  def annotate_invoke!(span, args)
44
36
  span.resource = name
45
37
  span.set_tag('rake.task.arg_names', arg_names)
@@ -56,7 +48,7 @@ module Datadog
56
48
  end
57
49
 
58
50
  def quantize_args(args)
59
- quantize_options = configuration[:quantize][:args]
51
+ quantize_options = Datadog.configuration[:rake][:quantize][:args]
60
52
  Datadog::Quantization::Hash.format(args, quantize_options)
61
53
  end
62
54
 
@@ -68,10 +60,6 @@ module Datadog
68
60
  configuration[:tracer]
69
61
  end
70
62
 
71
- def span_options
72
- { service: configuration[:service_name] }
73
- end
74
-
75
63
  def configuration
76
64
  Datadog.configuration[:rake]
77
65
  end
@@ -0,0 +1,33 @@
1
+ require 'ddtrace/registry'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ # Defines registerable behavior for integrations
6
+ module Registerable
7
+ def self.included(base)
8
+ base.send(:extend, ClassMethods)
9
+ base.send(:include, InstanceMethods)
10
+ end
11
+
12
+ # Class methods for registerable behavior
13
+ module ClassMethods
14
+ def register_as(name, options = {})
15
+ registry = options.fetch(:registry, Datadog.registry)
16
+ auto_patch = options.fetch(:auto_patch, false)
17
+
18
+ registry.add(name, new(name, options), auto_patch)
19
+ end
20
+ end
21
+
22
+ # Instance methods for registerable behavior
23
+ module InstanceMethods
24
+ attr_reader \
25
+ :name
26
+
27
+ def initialize(name, options = {})
28
+ @name = name
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -16,26 +16,18 @@ module Datadog
16
16
  yield
17
17
  span.service = pin.service
18
18
  end
19
+ ensure
20
+ pin.tracer.shutdown! if pin && pin.tracer
19
21
  end
20
22
  end
21
23
  end
22
24
  end
23
25
  end
24
26
 
25
- Resque.before_first_fork do
26
- pin = Datadog::Pin.get_from(Resque)
27
- next unless pin && pin.tracer
28
-
29
- # Create SyncWriter instance before forking
30
- sync_writer = Datadog::SyncWriter.new(transport: pin.tracer.writer.transport)
31
- Datadog::Contrib::Resque.sync_writer = sync_writer
32
- end
33
-
34
27
  Resque.after_fork do
35
28
  # get the current tracer
36
29
  pin = Datadog::Pin.get_from(Resque)
37
30
  next unless pin && pin.tracer
38
31
  # clean the state so no CoW happens
39
32
  pin.tracer.provider.context = nil
40
- pin.tracer.writer = Datadog::Contrib::Resque.sync_writer
41
33
  end
@@ -0,0 +1,13 @@
1
+ require 'ddtrace/contrib/configuration/settings'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ module Sequel
6
+ module Configuration
7
+ class Settings < Contrib::Configuration::Settings
8
+ # Add any custom Sequel settings or behavior here.
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -31,7 +31,7 @@ module Datadog
31
31
  def datadog_pin
32
32
  @pin ||= Datadog::Pin.new(
33
33
  Datadog.configuration[:sequel][:service_name] || adapter_name,
34
- app: Patcher::APP,
34
+ app: Integration::APP,
35
35
  app_type: Datadog::Ext::AppTypes::DB,
36
36
  tracer: Datadog.configuration[:sequel][:tracer] || Datadog.tracer
37
37
  )
@@ -0,0 +1,38 @@
1
+ require 'ddtrace/contrib/integration'
2
+ require 'ddtrace/contrib/sequel/configuration/settings'
3
+ require 'ddtrace/contrib/sequel/patcher'
4
+
5
+ module Datadog
6
+ module Contrib
7
+ module Sequel
8
+ # Description of Sequel integration
9
+ class Integration
10
+ include Contrib::Integration
11
+
12
+ APP = 'sequel'.freeze
13
+
14
+ register_as :sequel, auto_patch: false
15
+
16
+ def self.version
17
+ Gem.loaded_specs['sequel'] && Gem.loaded_specs['sequel'].version
18
+ end
19
+
20
+ def self.present?
21
+ super && defined?(::Sequel)
22
+ end
23
+
24
+ def self.compatible?
25
+ super && RUBY_VERSION >= '2.0.0'
26
+ end
27
+
28
+ def default_configuration
29
+ Configuration::Settings.new
30
+ end
31
+
32
+ def patcher
33
+ Patcher
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,4 @@
1
+ require 'ddtrace/contrib/patcher'
1
2
  require 'ddtrace/contrib/sequel/database'
2
3
  require 'ddtrace/contrib/sequel/dataset'
3
4
 
@@ -7,40 +8,23 @@ module Datadog
7
8
  # Patcher enables patching of 'sequel' module.
8
9
  # This is used in monkey.rb to manually apply patches
9
10
  module Patcher
10
- include Base
11
-
12
- APP = 'sequel'.freeze
13
-
14
- register_as :sequel, auto_patch: false
15
- option :service_name
16
- option :tracer, default: Datadog.tracer
17
-
18
- @patched = false
11
+ include Contrib::Patcher
19
12
 
20
13
  module_function
21
14
 
22
- # patched? tells whether patch has been successfully applied
23
15
  def patched?
24
- @patched
16
+ done?(:sequel)
25
17
  end
26
18
 
27
19
  def patch
28
- if !@patched && compatible?
20
+ do_once(:sequel) do
29
21
  begin
30
22
  patch_sequel_database
31
23
  patch_sequel_dataset
32
-
33
- @patched = true
34
24
  rescue StandardError => e
35
25
  Datadog::Tracer.log.error("Unable to apply Sequel integration: #{e}")
36
26
  end
37
27
  end
38
-
39
- @patched
40
- end
41
-
42
- def compatible?
43
- RUBY_VERSION >= '2.0.0' && defined?(::Sequel)
44
28
  end
45
29
 
46
30
  def patch_sequel_database
@@ -32,6 +32,11 @@ module Datadog
32
32
  @done_once[key] = true
33
33
  end
34
34
  end
35
+
36
+ def done?(key)
37
+ return false unless instance_variable_defined?(:@done_once)
38
+ !@done_once.nil? && @done_once.key?(key)
39
+ end
35
40
  end
36
41
 
37
42
  # Extend the common methods so they're available as a module function.