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
@@ -9,12 +9,6 @@ module Datadog
9
9
 
10
10
  # inject! popolates the env with span ID, trace ID and sampling priority
11
11
  def self.inject!(context, env)
12
- # Prevent propagation from being attempted if context provided is nil.
13
- if context.nil?
14
- Datadog::Tracer.log.debug('Cannot inject context into env to propagate over HTTP: context is nil.'.freeze)
15
- return
16
- end
17
-
18
12
  env[HTTP_HEADER_TRACE_ID] = context.trace_id.to_s
19
13
  env[HTTP_HEADER_PARENT_ID] = context.span_id.to_s
20
14
  env[HTTP_HEADER_SAMPLING_PRIORITY] = context.sampling_priority.to_s
@@ -24,6 +24,7 @@ module Datadog
24
24
  attr_writer :default_service
25
25
 
26
26
  ALLOWED_SPAN_OPTIONS = [:service, :resource, :span_type].freeze
27
+ DEFAULT_ON_ERROR = proc { |span, error| span.set_error(error) unless span.nil? }
27
28
 
28
29
  # Global, memoized, lazy initialized instance of a logger that is used within the the Datadog
29
30
  # namespace. This logger outputs to +STDOUT+ by default, and is considered thread-safe.
@@ -277,14 +278,23 @@ module Datadog
277
278
  # * +tags+: extra tags which should be added to the span.
278
279
  def trace(name, options = {})
279
280
  options[:child_of] = call_context
280
- span = start_span(name, options)
281
281
 
282
282
  # call the finish only if a block is given; this ensures
283
283
  # that a call to tracer.trace() without a block, returns
284
284
  # a span that should be manually finished.
285
285
  if block_given?
286
+ span = nil
287
+ return_value = nil
288
+
286
289
  begin
287
- yield(span)
290
+ begin
291
+ span = start_span(name, options)
292
+ # rubocop:disable Lint/UselessAssignment
293
+ rescue StandardError => e
294
+ Datadog::Tracer.log.debug('Failed to start span: #{e}')
295
+ ensure
296
+ return_value = yield(span)
297
+ end
288
298
  # rubocop:disable Lint/RescueException
289
299
  # Here we really want to catch *any* exception, not only StandardError,
290
300
  # as we really have no clue of what is in the block,
@@ -292,13 +302,15 @@ module Datadog
292
302
  # It's not a problem since we re-raise it afterwards so for example a
293
303
  # SignalException::Interrupt would still bubble up.
294
304
  rescue Exception => e
295
- span.set_error(e)
305
+ (options[:on_error] || DEFAULT_ON_ERROR).call(span, e)
296
306
  raise e
297
307
  ensure
298
- span.finish()
308
+ span.finish unless span.nil?
299
309
  end
310
+
311
+ return_value
300
312
  else
301
- span
313
+ start_span(name, options)
302
314
  end
303
315
  end
304
316
 
@@ -0,0 +1,301 @@
1
+ require 'uri'
2
+
3
+ # NOTE: This code is copied directly from ActiveRecord.
4
+ # Its purpose is to resolve connection information.
5
+ # It exists here only because it doesn't exist in Rails 3.2.
6
+ # When support for Rails 3.2 is dropped, this can be removed.
7
+ module Datadog
8
+ module Vendor
9
+ module ActiveRecord
10
+ # Copy/paste from:
11
+ # https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_handling.rb
12
+ module ConnectionHandling
13
+ RAILS_ENV = -> { (Rails.env if defined?(Rails) && defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
14
+ end
15
+
16
+ # Copy/paste from:
17
+ # https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/connection_specification.rb
18
+ module ConnectionAdapters
19
+ class ConnectionSpecification
20
+ attr_reader :name, :config, :adapter_method
21
+
22
+ def initialize(name, config, adapter_method)
23
+ @name, @config, @adapter_method = name, config, adapter_method
24
+ end
25
+
26
+ def initialize_dup(original)
27
+ @config = original.config.dup
28
+ end
29
+
30
+ def to_hash
31
+ @config.merge(name: @name)
32
+ end
33
+
34
+ # Expands a connection string into a hash.
35
+ class ConnectionUrlResolver # :nodoc:
36
+ # == Example
37
+ #
38
+ # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
39
+ # ConnectionUrlResolver.new(url).to_hash
40
+ # # => {
41
+ # "adapter" => "postgresql",
42
+ # "host" => "localhost",
43
+ # "port" => 9000,
44
+ # "database" => "foo_test",
45
+ # "username" => "foo",
46
+ # "password" => "bar",
47
+ # "pool" => "5",
48
+ # "timeout" => "3000"
49
+ # }
50
+ def initialize(url)
51
+ raise "Database URL cannot be empty" if url.blank?
52
+ @uri = uri_parser.parse(url)
53
+ @adapter = @uri.scheme && @uri.scheme.tr("-", "_")
54
+ @adapter = "postgresql" if @adapter == "postgres"
55
+
56
+ if @uri.opaque
57
+ @uri.opaque, @query = @uri.opaque.split("?", 2)
58
+ else
59
+ @query = @uri.query
60
+ end
61
+ end
62
+
63
+ # Converts the given URL to a full connection hash.
64
+ def to_hash
65
+ config = raw_config.reject { |_, value| value.blank? }
66
+ config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
67
+ config
68
+ end
69
+
70
+ private
71
+
72
+ def uri
73
+ @uri
74
+ end
75
+
76
+ def uri_parser
77
+ @uri_parser ||= URI::Parser.new
78
+ end
79
+
80
+ # Converts the query parameters of the URI into a hash.
81
+ #
82
+ # "localhost?pool=5&reaping_frequency=2"
83
+ # # => { "pool" => "5", "reaping_frequency" => "2" }
84
+ #
85
+ # returns empty hash if no query present.
86
+ #
87
+ # "localhost"
88
+ # # => {}
89
+ def query_hash
90
+ Hash[(@query || "").split("&").map { |pair| pair.split("=") }]
91
+ end
92
+
93
+ def raw_config
94
+ if uri.opaque
95
+ query_hash.merge(
96
+ "adapter" => @adapter,
97
+ "database" => uri.opaque)
98
+ else
99
+ query_hash.merge(
100
+ "adapter" => @adapter,
101
+ "username" => uri.user,
102
+ "password" => uri.password,
103
+ "port" => uri.port,
104
+ "database" => database_from_path,
105
+ "host" => uri.hostname)
106
+ end
107
+ end
108
+
109
+ # Returns name of the database.
110
+ def database_from_path
111
+ if @adapter == "sqlite3"
112
+ # 'sqlite3:/foo' is absolute, because that makes sense. The
113
+ # corresponding relative version, 'sqlite3:foo', is handled
114
+ # elsewhere, as an "opaque".
115
+
116
+ uri.path
117
+ else
118
+ # Only SQLite uses a filename as the "database" name; for
119
+ # anything else, a leading slash would be silly.
120
+
121
+ uri.path.sub(%r{^/}, "")
122
+ end
123
+ end
124
+ end
125
+
126
+ ##
127
+ # Builds a ConnectionSpecification from user input.
128
+ class Resolver # :nodoc:
129
+ attr_reader :configurations
130
+
131
+ # Accepts a hash two layers deep, keys on the first layer represent
132
+ # environments such as "production". Keys must be strings.
133
+ def initialize(configurations)
134
+ @configurations = configurations
135
+ end
136
+
137
+ # Returns a hash with database connection information.
138
+ #
139
+ # == Examples
140
+ #
141
+ # Full hash Configuration.
142
+ #
143
+ # configurations = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
144
+ # Resolver.new(configurations).resolve(:production)
145
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3"}
146
+ #
147
+ # Initialized with URL configuration strings.
148
+ #
149
+ # configurations = { "production" => "postgresql://localhost/foo" }
150
+ # Resolver.new(configurations).resolve(:production)
151
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
152
+ #
153
+ def resolve(config)
154
+ if config
155
+ resolve_connection config
156
+ elsif env = ConnectionHandling::RAILS_ENV.call
157
+ resolve_symbol_connection env.to_sym
158
+ else
159
+ raise AdapterNotSpecified
160
+ end
161
+ end
162
+
163
+ # Expands each key in @configurations hash into fully resolved hash
164
+ def resolve_all
165
+ config = configurations.dup
166
+
167
+ if env = ConnectionHandling::DEFAULT_ENV.call
168
+ env_config = config[env] if config[env].is_a?(Hash) && !(config[env].key?("adapter") || config[env].key?("url"))
169
+ end
170
+
171
+ config.reject! { |k, v| v.is_a?(Hash) && !(v.key?("adapter") || v.key?("url")) }
172
+ config.merge! env_config if env_config
173
+
174
+ config.each do |key, value|
175
+ config[key] = resolve(value) if value
176
+ end
177
+
178
+ config
179
+ end
180
+
181
+ # Returns an instance of ConnectionSpecification for a given adapter.
182
+ # Accepts a hash one layer deep that contains all connection information.
183
+ #
184
+ # == Example
185
+ #
186
+ # config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
187
+ # spec = Resolver.new(config).spec(:production)
188
+ # spec.adapter_method
189
+ # # => "sqlite3_connection"
190
+ # spec.config
191
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
192
+ #
193
+ def spec(config)
194
+ spec = resolve(config).symbolize_keys
195
+
196
+ raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
197
+
198
+ # Require the adapter itself and give useful feedback about
199
+ # 1. Missing adapter gems and
200
+ # 2. Adapter gems' missing dependencies.
201
+ path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
202
+ begin
203
+ require path_to_adapter
204
+ rescue LoadError => e
205
+ # We couldn't require the adapter itself. Raise an exception that
206
+ # points out config typos and missing gems.
207
+ if e.path == path_to_adapter
208
+ # We can assume that a non-builtin adapter was specified, so it's
209
+ # either misspelled or missing from Gemfile.
210
+ raise e.class, "Could not load the '#{spec[:adapter]}' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
211
+
212
+ # Bubbled up from the adapter require. Prefix the exception message
213
+ # with some guidance about how to address it and reraise.
214
+ else
215
+ raise e.class, "Error loading the '#{spec[:adapter]}' Active Record adapter. Missing a gem it depends on? #{e.message}", e.backtrace
216
+ end
217
+ end
218
+
219
+ adapter_method = "#{spec[:adapter]}_connection"
220
+
221
+ unless ::ActiveRecord::Base.respond_to?(adapter_method)
222
+ raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
223
+ end
224
+
225
+ ConnectionSpecification.new(spec.delete(:name) || "primary", spec, adapter_method)
226
+ end
227
+
228
+ private
229
+
230
+ # Returns fully resolved connection, accepts hash, string or symbol.
231
+ # Always returns a hash.
232
+ #
233
+ # == Examples
234
+ #
235
+ # Symbol representing current environment.
236
+ #
237
+ # Resolver.new("production" => {}).resolve_connection(:production)
238
+ # # => {}
239
+ #
240
+ # One layer deep hash of connection values.
241
+ #
242
+ # Resolver.new({}).resolve_connection("adapter" => "sqlite3")
243
+ # # => { "adapter" => "sqlite3" }
244
+ #
245
+ # Connection URL.
246
+ #
247
+ # Resolver.new({}).resolve_connection("postgresql://localhost/foo")
248
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
249
+ #
250
+ def resolve_connection(spec)
251
+ case spec
252
+ when Symbol
253
+ resolve_symbol_connection spec
254
+ when String
255
+ resolve_url_connection spec
256
+ when Hash
257
+ resolve_hash_connection spec
258
+ end
259
+ end
260
+
261
+ # Takes the environment such as +:production+ or +:development+.
262
+ # This requires that the @configurations was initialized with a key that
263
+ # matches.
264
+ #
265
+ # Resolver.new("production" => {}).resolve_symbol_connection(:production)
266
+ # # => {}
267
+ #
268
+ def resolve_symbol_connection(spec)
269
+ if config = configurations[spec.to_s]
270
+ resolve_connection(config).merge("name" => spec.to_s)
271
+ else
272
+ raise(AdapterNotSpecified, "'#{spec}' database is not configured. Available: #{configurations.keys.inspect}")
273
+ end
274
+ end
275
+
276
+ # Accepts a hash. Expands the "url" key that contains a
277
+ # URL database connection to a full connection
278
+ # hash and merges with the rest of the hash.
279
+ # Connection details inside of the "url" key win any merge conflicts
280
+ def resolve_hash_connection(spec)
281
+ if spec["url"] && spec["url"] !~ /^jdbc:/
282
+ connection_hash = resolve_url_connection(spec.delete("url"))
283
+ spec.merge!(connection_hash)
284
+ end
285
+ spec
286
+ end
287
+
288
+ # Takes a connection URL.
289
+ #
290
+ # Resolver.new({}).resolve_url_connection("postgresql://localhost/foo")
291
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
292
+ #
293
+ def resolve_url_connection(url)
294
+ ConnectionUrlResolver.new(url).to_hash
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end
@@ -1,9 +1,9 @@
1
1
  module Datadog
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 13
5
- PATCH = 2
6
- PRE = nil
4
+ MINOR = 14
5
+ PATCH = 0
6
+ PRE = 'beta1'.freeze
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.14.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-07 00:00:00.000000000 Z
11
+ date: 2018-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -282,10 +282,13 @@ files:
282
282
  - lib/ddtrace/contrib/active_model_serializers/events/render.rb
283
283
  - lib/ddtrace/contrib/active_model_serializers/events/serialize.rb
284
284
  - lib/ddtrace/contrib/active_model_serializers/patcher.rb
285
+ - lib/ddtrace/contrib/active_record/configuration/resolver.rb
286
+ - lib/ddtrace/contrib/active_record/configuration/settings.rb
285
287
  - lib/ddtrace/contrib/active_record/event.rb
286
288
  - lib/ddtrace/contrib/active_record/events.rb
287
289
  - lib/ddtrace/contrib/active_record/events/instantiation.rb
288
290
  - lib/ddtrace/contrib/active_record/events/sql.rb
291
+ - lib/ddtrace/contrib/active_record/integration.rb
289
292
  - lib/ddtrace/contrib/active_record/patcher.rb
290
293
  - lib/ddtrace/contrib/active_record/utils.rb
291
294
  - lib/ddtrace/contrib/active_support/notifications/event.rb
@@ -296,9 +299,19 @@ files:
296
299
  - lib/ddtrace/contrib/aws/patcher.rb
297
300
  - lib/ddtrace/contrib/aws/services.rb
298
301
  - lib/ddtrace/contrib/base.rb
302
+ - lib/ddtrace/contrib/configurable.rb
303
+ - lib/ddtrace/contrib/configuration/option.rb
304
+ - lib/ddtrace/contrib/configuration/option_definition.rb
305
+ - lib/ddtrace/contrib/configuration/option_definition_set.rb
306
+ - lib/ddtrace/contrib/configuration/option_set.rb
307
+ - lib/ddtrace/contrib/configuration/options.rb
308
+ - lib/ddtrace/contrib/configuration/resolver.rb
309
+ - lib/ddtrace/contrib/configuration/settings.rb
299
310
  - lib/ddtrace/contrib/dalli/instrumentation.rb
300
311
  - lib/ddtrace/contrib/dalli/patcher.rb
301
312
  - lib/ddtrace/contrib/dalli/quantize.rb
313
+ - lib/ddtrace/contrib/delayed_job/patcher.rb
314
+ - lib/ddtrace/contrib/delayed_job/plugin.rb
302
315
  - lib/ddtrace/contrib/elasticsearch/patcher.rb
303
316
  - lib/ddtrace/contrib/elasticsearch/quantize.rb
304
317
  - lib/ddtrace/contrib/excon/middleware.rb
@@ -314,11 +327,14 @@ files:
314
327
  - lib/ddtrace/contrib/grpc/intercept_with_datadog.rb
315
328
  - lib/ddtrace/contrib/grpc/patcher.rb
316
329
  - lib/ddtrace/contrib/http/patcher.rb
330
+ - lib/ddtrace/contrib/integration.rb
317
331
  - lib/ddtrace/contrib/mongodb/parsers.rb
318
332
  - lib/ddtrace/contrib/mongodb/patcher.rb
319
333
  - lib/ddtrace/contrib/mongodb/subscribers.rb
320
334
  - lib/ddtrace/contrib/mysql2/client.rb
321
335
  - lib/ddtrace/contrib/mysql2/patcher.rb
336
+ - lib/ddtrace/contrib/patchable.rb
337
+ - lib/ddtrace/contrib/patcher.rb
322
338
  - lib/ddtrace/contrib/racecar/event.rb
323
339
  - lib/ddtrace/contrib/racecar/events.rb
324
340
  - lib/ddtrace/contrib/racecar/events/batch.rb
@@ -342,10 +358,13 @@ files:
342
358
  - lib/ddtrace/contrib/redis/patcher.rb
343
359
  - lib/ddtrace/contrib/redis/quantize.rb
344
360
  - lib/ddtrace/contrib/redis/tags.rb
361
+ - lib/ddtrace/contrib/registerable.rb
345
362
  - lib/ddtrace/contrib/resque/patcher.rb
346
363
  - lib/ddtrace/contrib/resque/resque_job.rb
364
+ - lib/ddtrace/contrib/sequel/configuration/settings.rb
347
365
  - lib/ddtrace/contrib/sequel/database.rb
348
366
  - lib/ddtrace/contrib/sequel/dataset.rb
367
+ - lib/ddtrace/contrib/sequel/integration.rb
349
368
  - lib/ddtrace/contrib/sequel/patcher.rb
350
369
  - lib/ddtrace/contrib/sequel/utils.rb
351
370
  - lib/ddtrace/contrib/sidekiq/patcher.rb
@@ -392,6 +411,7 @@ files:
392
411
  - lib/ddtrace/transport.rb
393
412
  - lib/ddtrace/utils.rb
394
413
  - lib/ddtrace/utils/database.rb
414
+ - lib/ddtrace/vendor/active_record/connection_specification.rb
395
415
  - lib/ddtrace/version.rb
396
416
  - lib/ddtrace/workers.rb
397
417
  - lib/ddtrace/writer.rb
@@ -411,9 +431,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
411
431
  version: 1.9.1
412
432
  required_rubygems_version: !ruby/object:Gem::Requirement
413
433
  requirements:
414
- - - ">="
434
+ - - ">"
415
435
  - !ruby/object:Gem::Version
416
- version: '0'
436
+ version: 1.3.1
417
437
  requirements: []
418
438
  rubyforge_project:
419
439
  rubygems_version: 2.7.7