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.
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.