fair-ddtrace 0.8.2.a

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 (77) hide show
  1. checksums.yaml +7 -0
  2. data/.env +11 -0
  3. data/.gitignore +59 -0
  4. data/.rubocop.yml +61 -0
  5. data/.yardopts +5 -0
  6. data/Appraisals +136 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +24 -0
  9. data/README.md +156 -0
  10. data/Rakefile +176 -0
  11. data/circle.yml +61 -0
  12. data/ddtrace.gemspec +44 -0
  13. data/docker-compose.yml +42 -0
  14. data/docs/GettingStarted.md +735 -0
  15. data/gemfiles/contrib.gemfile +16 -0
  16. data/gemfiles/contrib_old.gemfile +15 -0
  17. data/gemfiles/rails30_postgres.gemfile +10 -0
  18. data/gemfiles/rails30_postgres_sidekiq.gemfile +11 -0
  19. data/gemfiles/rails32_mysql2.gemfile +11 -0
  20. data/gemfiles/rails32_postgres.gemfile +10 -0
  21. data/gemfiles/rails32_postgres_redis.gemfile +11 -0
  22. data/gemfiles/rails32_postgres_sidekiq.gemfile +11 -0
  23. data/gemfiles/rails4_mysql2.gemfile +9 -0
  24. data/gemfiles/rails4_postgres.gemfile +9 -0
  25. data/gemfiles/rails4_postgres_redis.gemfile +10 -0
  26. data/gemfiles/rails4_postgres_sidekiq.gemfile +11 -0
  27. data/gemfiles/rails5_mysql2.gemfile +8 -0
  28. data/gemfiles/rails5_postgres.gemfile +8 -0
  29. data/gemfiles/rails5_postgres_redis.gemfile +9 -0
  30. data/gemfiles/rails5_postgres_sidekiq.gemfile +10 -0
  31. data/lib/ddtrace.rb +73 -0
  32. data/lib/ddtrace/buffer.rb +52 -0
  33. data/lib/ddtrace/context.rb +145 -0
  34. data/lib/ddtrace/contrib/active_record/patcher.rb +94 -0
  35. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +108 -0
  36. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +22 -0
  37. data/lib/ddtrace/contrib/grape/endpoint.rb +164 -0
  38. data/lib/ddtrace/contrib/grape/patcher.rb +73 -0
  39. data/lib/ddtrace/contrib/http/patcher.rb +156 -0
  40. data/lib/ddtrace/contrib/rack/middlewares.rb +150 -0
  41. data/lib/ddtrace/contrib/rails/action_controller.rb +81 -0
  42. data/lib/ddtrace/contrib/rails/action_view.rb +110 -0
  43. data/lib/ddtrace/contrib/rails/active_record.rb +56 -0
  44. data/lib/ddtrace/contrib/rails/active_support.rb +113 -0
  45. data/lib/ddtrace/contrib/rails/core_extensions.rb +137 -0
  46. data/lib/ddtrace/contrib/rails/framework.rb +171 -0
  47. data/lib/ddtrace/contrib/rails/middlewares.rb +32 -0
  48. data/lib/ddtrace/contrib/rails/utils.rb +43 -0
  49. data/lib/ddtrace/contrib/redis/patcher.rb +118 -0
  50. data/lib/ddtrace/contrib/redis/quantize.rb +30 -0
  51. data/lib/ddtrace/contrib/redis/tags.rb +19 -0
  52. data/lib/ddtrace/contrib/sidekiq/tracer.rb +103 -0
  53. data/lib/ddtrace/contrib/sinatra/tracer.rb +169 -0
  54. data/lib/ddtrace/distributed.rb +38 -0
  55. data/lib/ddtrace/encoding.rb +65 -0
  56. data/lib/ddtrace/error.rb +37 -0
  57. data/lib/ddtrace/ext/app_types.rb +10 -0
  58. data/lib/ddtrace/ext/cache.rb +7 -0
  59. data/lib/ddtrace/ext/distributed.rb +10 -0
  60. data/lib/ddtrace/ext/errors.rb +10 -0
  61. data/lib/ddtrace/ext/http.rb +11 -0
  62. data/lib/ddtrace/ext/net.rb +8 -0
  63. data/lib/ddtrace/ext/redis.rb +11 -0
  64. data/lib/ddtrace/ext/sql.rb +8 -0
  65. data/lib/ddtrace/logger.rb +39 -0
  66. data/lib/ddtrace/monkey.rb +84 -0
  67. data/lib/ddtrace/pin.rb +63 -0
  68. data/lib/ddtrace/provider.rb +21 -0
  69. data/lib/ddtrace/sampler.rb +49 -0
  70. data/lib/ddtrace/span.rb +222 -0
  71. data/lib/ddtrace/tracer.rb +310 -0
  72. data/lib/ddtrace/transport.rb +162 -0
  73. data/lib/ddtrace/utils.rb +16 -0
  74. data/lib/ddtrace/version.rb +9 -0
  75. data/lib/ddtrace/workers.rb +108 -0
  76. data/lib/ddtrace/writer.rb +118 -0
  77. metadata +208 -0
@@ -0,0 +1,16 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "elasticsearch-transport"
6
+ gem "grape"
7
+ gem "rack"
8
+ gem "rack-test"
9
+ gem "redis"
10
+ gem "hiredis"
11
+ gem "sinatra"
12
+ gem "sqlite3"
13
+ gem "activerecord"
14
+ gem "sidekiq"
15
+
16
+ gemspec path: "../"
@@ -0,0 +1,15 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "elasticsearch-transport"
6
+ gem "redis", "< 4.0.0"
7
+ gem "hiredis"
8
+ gem "rack", "1.4.7"
9
+ gem "rack-test"
10
+ gem "sinatra", "1.4.5"
11
+ gem "sqlite3"
12
+ gem "activerecord", "3.2.22.5"
13
+ gem "sidekiq", "4.0.0"
14
+
15
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit"
6
+ gem "rails", "3.0.20"
7
+ gem "pg", "0.15.1", platform: :ruby
8
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit"
6
+ gem "rails", "3.0.20"
7
+ gem "pg", "0.15.1", platform: :ruby
8
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
9
+ gem "sidekiq", "4.0.0"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit"
6
+ gem "rails", "3.2.22.5"
7
+ gem "mysql2", "0.3.21", platform: :ruby
8
+ gem "activerecord-mysql-adapter", platform: :ruby
9
+ gem "activerecord-jdbcmysql-adapter", platform: :jruby
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit"
6
+ gem "rails", "3.2.22.5"
7
+ gem "pg", "0.15.1", platform: :ruby
8
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit"
6
+ gem "rails", "3.2.22.5"
7
+ gem "pg", "0.15.1", platform: :ruby
8
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
9
+ gem "redis-rails"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit"
6
+ gem "rails", "3.2.22.5"
7
+ gem "pg", "0.15.1", platform: :ruby
8
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
9
+ gem "sidekiq", "4.0.0"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "4.2.7.1"
6
+ gem "mysql2", platform: :ruby
7
+ gem "activerecord-jdbcmysql-adapter", platform: :jruby
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "4.2.7.1"
6
+ gem "pg", platform: :ruby
7
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "4.2.7.1"
6
+ gem "pg", platform: :ruby
7
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
8
+ gem "redis-rails"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "4.2.7.1"
6
+ gem "pg", platform: :ruby
7
+ gem "activerecord-jdbcpostgresql-adapter", platform: :jruby
8
+ gem "sidekiq"
9
+ gem "activejob"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.0.1"
6
+ gem "mysql2", platform: :ruby
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.0.1"
6
+ gem "pg", platform: :ruby
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.0.1"
6
+ gem "pg", platform: :ruby
7
+ gem "redis-rails"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.0.1"
6
+ gem "pg", platform: :ruby
7
+ gem "sidekiq"
8
+ gem "activejob"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,73 @@
1
+ require 'ddtrace/monkey'
2
+ require 'ddtrace/pin'
3
+ require 'ddtrace/tracer'
4
+ require 'ddtrace/error'
5
+
6
+ # \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
7
+ module Datadog
8
+ @tracer = Datadog::Tracer.new()
9
+
10
+ # Default tracer that can be used as soon as +ddtrace+ is required:
11
+ #
12
+ # require 'ddtrace'
13
+ #
14
+ # span = Datadog.tracer.trace('web.request')
15
+ # span.finish()
16
+ #
17
+ # If you want to override the default tracer, the recommended way
18
+ # is to "pin" your own tracer onto your traced component:
19
+ #
20
+ # tracer = Datadog::Tracer.new
21
+ # pin = Datadog::Pin.get_from(mypatchcomponent)
22
+ # pin.tracer = tracer
23
+
24
+ def self.tracer
25
+ @tracer
26
+ end
27
+ end
28
+
29
+ # Datadog auto instrumentation for frameworks
30
+ if defined?(Rails::VERSION)
31
+ if !ENV['DISABLE_DATADOG_RAILS']
32
+ if Rails::VERSION::MAJOR.to_i >= 3
33
+ require 'ddtrace/contrib/rails/framework'
34
+ require 'ddtrace/contrib/rails/middlewares'
35
+
36
+ module Datadog
37
+ # Railtie class initializes
38
+ class Railtie < Rails::Railtie
39
+ config.app_middleware.use(Datadog::Contrib::Rails::ExceptionMiddleware)
40
+
41
+ # auto instrument Rails and third party components after
42
+ # the framework initialization
43
+ options = {}
44
+ config.after_initialize do |app|
45
+ Datadog::Contrib::Rails::Framework.configure(config: app.config)
46
+ Datadog::Contrib::Rails::Framework.auto_instrument()
47
+ Datadog::Contrib::Rails::Framework.auto_instrument_redis()
48
+ Datadog::Contrib::Rails::Framework.auto_instrument_grape()
49
+
50
+ # override Rack Middleware configurations with Rails
51
+ options.update(::Rails.configuration.datadog_trace)
52
+ end
53
+
54
+ # Configure datadog settings before building the middleware stack.
55
+ # This is required because the middleware stack is frozen after
56
+ # the initialization and so it's too late to add our tracing
57
+ # functionalities.
58
+ initializer :datadog_config, before: :build_middleware_stack do |app|
59
+ app.config.middleware.insert_before(
60
+ 0, Datadog::Contrib::Rack::TraceMiddleware, options
61
+ )
62
+ end
63
+ end
64
+ end
65
+ else
66
+ Datadog::Tracer.log.warn 'Detected a Rails version < 3.x.'\
67
+ 'This version is not supported yet and the'\
68
+ 'auto-instrumentation for core components will be disabled.'
69
+ end
70
+ else
71
+ Datadog::Tracer.log.info 'Skipping Rails auto-instrumentation, DISABLE_DATADOG_RAILS is set.'
72
+ end
73
+ end
@@ -0,0 +1,52 @@
1
+ require 'thread'
2
+
3
+ module Datadog
4
+ # Trace buffer that stores application traces. The buffer has a maximum size and when
5
+ # the buffer is full, a random trace is discarded. This class is thread-safe and is used
6
+ # automatically by the ``Tracer`` instance when a ``Span`` is finished.
7
+ class TraceBuffer
8
+ def initialize(max_size)
9
+ @max_size = max_size
10
+
11
+ @mutex = Mutex.new()
12
+ @traces = []
13
+ end
14
+
15
+ # Add a new ``trace`` in the local queue. This method doesn't block the execution
16
+ # even if the buffer is full. In that case, a random trace is discarded.
17
+ def push(trace)
18
+ @mutex.synchronize do
19
+ len = @traces.length
20
+ if len < @max_size || @max_size <= 0
21
+ @traces << trace
22
+ else
23
+ # we should replace a random trace with the new one
24
+ @traces[rand(len)] = trace
25
+ end
26
+ end
27
+ end
28
+
29
+ # Return the current number of stored traces.
30
+ def length
31
+ @mutex.synchronize do
32
+ return @traces.length
33
+ end
34
+ end
35
+
36
+ # Return if the buffer is empty.
37
+ def empty?
38
+ @mutex.synchronize do
39
+ return @traces.empty?
40
+ end
41
+ end
42
+
43
+ # Stored traces are returned and the local buffer is reset.
44
+ def pop
45
+ @mutex.synchronize do
46
+ traces = @traces
47
+ @traces = []
48
+ return traces
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,145 @@
1
+ require 'thread'
2
+
3
+ module Datadog
4
+ # \Context is used to keep track of a hierarchy of spans for the current
5
+ # execution flow. During each logical execution, the same \Context is
6
+ # used to represent a single logical trace, even if the trace is built
7
+ # asynchronously.
8
+ #
9
+ # A single code execution may use multiple \Context if part of the execution
10
+ # must not be related to the current tracing. As example, a delayed job may
11
+ # compose a standalone trace instead of being related to the same trace that
12
+ # generates the job itself. On the other hand, if it's part of the same
13
+ # \Context, it will be related to the original trace.
14
+ #
15
+ # This data structure is thread-safe.
16
+ class Context
17
+ # Initialize a new thread-safe \Context.
18
+ def initialize
19
+ @mutex = Mutex.new
20
+ reset
21
+ end
22
+
23
+ def reset
24
+ @trace = []
25
+ @sampled = false
26
+ @finished_spans = 0
27
+ @current_span = nil
28
+ end
29
+
30
+ # Return the last active span that corresponds to the last inserted
31
+ # item in the trace list. This cannot be considered as the current active
32
+ # span in asynchronous environments, because some spans can be closed
33
+ # earlier while child spans still need to finish their traced execution.
34
+ def current_span
35
+ @mutex.synchronize do
36
+ return @current_span
37
+ end
38
+ end
39
+
40
+ # Add a span to the context trace list, keeping it as the last active span.
41
+ def add_span(span)
42
+ @mutex.synchronize do
43
+ @current_span = span
44
+ @sampled = span.sampled
45
+ @trace << span
46
+ span.context = self
47
+ end
48
+ end
49
+
50
+ # Mark a span as a finished, increasing the internal counter to prevent
51
+ # cycles inside _trace list.
52
+ def close_span(span)
53
+ @mutex.synchronize do
54
+ @finished_spans += 1
55
+ # Current span is only meaningful for linear tree-like traces,
56
+ # in other cases, this is just broken and one should rely
57
+ # on per-instrumentation code to retrieve handle parent/child relations.
58
+ @current_span = span.parent
59
+ return if span.tracer.nil?
60
+ return unless Datadog::Tracer.debug_logging
61
+ if span.parent.nil? && !check_finished_spans
62
+ opened_spans = @trace.length - @finished_spans
63
+ Datadog::Tracer.log.debug("root span #{span.name} closed but has #{opened_spans} unfinished spans:")
64
+ @trace.each do |s|
65
+ Datadog::Tracer.log.debug("unfinished span: #{s}") unless s.finished?
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ # Returns if the trace for the current Context is finished or not.
72
+ # Low-level internal function, not thread-safe.
73
+ def check_finished_spans
74
+ @finished_spans > 0 && @trace.length == @finished_spans
75
+ end
76
+
77
+ # Returns if the trace for the current Context is finished or not. A \Context
78
+ # is considered finished if all spans in this context are finished.
79
+ def finished?
80
+ @mutex.synchronize do
81
+ return check_finished_spans
82
+ end
83
+ end
84
+
85
+ # Returns true if the context is sampled, that is, if it should be kept
86
+ # and sent to the trace agent.
87
+ def sampled?
88
+ @mutex.synchronize do
89
+ return @sampled
90
+ end
91
+ end
92
+
93
+ # Returns both the trace list generated in the current context and
94
+ # if the context is sampled or not. It returns nil, nil if the ``Context`` is
95
+ # not finished. If a trace is returned, the \Context will be reset so that it
96
+ # can be re-used immediately.
97
+ #
98
+ # This operation is thread-safe.
99
+ def get
100
+ @mutex.synchronize do
101
+ return nil, nil unless check_finished_spans
102
+
103
+ trace = @trace
104
+ sampled = @sampled
105
+ reset
106
+ return trace, sampled
107
+ end
108
+ end
109
+
110
+ # Return a string representation of the context.
111
+ def to_s
112
+ @mutex.synchronize do
113
+ # rubocop:disable Metrics/LineLength
114
+ "Context(trace.length:#{@trace.length},sampled:#{@sampled},finished_spans:#{@finished_spans},current_span:#{@current_span})"
115
+ end
116
+ end
117
+
118
+ private :reset
119
+ private :check_finished_spans
120
+ end
121
+
122
+ # ThreadLocalContext can be used as a tracer global reference to create
123
+ # a different \Context for each thread. In synchronous tracer, this
124
+ # is required to prevent multiple threads sharing the same \Context
125
+ # in different executions.
126
+ class ThreadLocalContext
127
+ # ThreadLocalContext can be used as a tracer global reference to create
128
+ # a different \Context for each thread. In synchronous tracer, this
129
+ # is required to prevent multiple threads sharing the same \Context
130
+ # in different executions.
131
+ def initialize
132
+ self.local = Datadog::Context.new
133
+ end
134
+
135
+ # Override the thread-local context with a new context.
136
+ def local=(ctx)
137
+ Thread.current[:datadog_context] = ctx
138
+ end
139
+
140
+ # Return the thread-local context.
141
+ def local
142
+ Thread.current[:datadog_context] ||= Datadog::Context.new
143
+ end
144
+ end
145
+ end