ddtrace 0.18.3 → 0.19.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 690c74d7e00a2fabf4ad03e30b0b40656c8337e9
4
- data.tar.gz: dc9f24349943d09fd472b0e5cb9c3b1cff1685ca
3
+ metadata.gz: f812f568118b7998a52208ffdb4c90a253edfd67
4
+ data.tar.gz: 914ce035245993d7535152437c720c8c3cca3c2e
5
5
  SHA512:
6
- metadata.gz: e996f0517f9be72b1b81d36eeedf099f997e66b0d00da4ad4cd93e169a93b6dbcb7e5a8b7df466b11b6487a82236ecfb9c997c908b1337a336c34e07ac78a7be
7
- data.tar.gz: 6973e5ff265f3660a19836dd7b02fba398583429c5364e4140cf3231341b855c06596ef33a2a92376f70ead4545326f591a1275ff342f0aba043c1f9ef9dbe46
6
+ metadata.gz: '08f6d5fe32d68feb4c38ef89ef43908c76884d1b92b30929fc3edd7c50fad58674d21f7e00ff97e4731b008213e9e0584106691d52ed8b1feb16b0dbdac877a0'
7
+ data.tar.gz: 8b452ada6e2cfb91d1ee170600dc3fc7cd17c0b37042c6a3a746cc5739da038b37457204194f8ecdbc802a85d5afcdb4e79d13bf31293c2226aa0d62dcd0fa66
data/CHANGELOG.md CHANGED
@@ -4,6 +4,21 @@
4
4
 
5
5
  ## [Unreleased (beta)]
6
6
 
7
+ ## [0.19.0] - 2019-01-22
8
+
9
+ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.19.0
10
+
11
+ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.18.3...v0.19.0
12
+
13
+ ### Added
14
+
15
+ - Tracer#active_correlation for adding correlation IDs to logs. (#660, #664, #673)
16
+ - Opt-in support for `event_sample_rate` tag for some integrations. (#665, #666)
17
+
18
+ ### Changed
19
+
20
+ - Priority sampling enabled by default. (#654)
21
+
7
22
  ## [0.18.3] - 2019-01-17
8
23
 
9
24
  Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.18.3
@@ -627,8 +642,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
627
642
 
628
643
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
629
644
 
630
- [Unreleased (stable)]: https://github.com/DataDog/dd-trace-rb/compare/v0.18.3...master
631
- [Unreleased (beta)]: https://github.com/DataDog/dd-trace-rb/compare/v0.18.3...0.19-dev
645
+ [Unreleased (stable)]: https://github.com/DataDog/dd-trace-rb/compare/v0.19.0...master
646
+ [Unreleased (beta)]: https://github.com/DataDog/dd-trace-rb/compare/v0.19.0...0.20-dev
647
+ [0.19.0]: https://github.com/DataDog/dd-trace-rb/compare/v0.18.3...v0.19.0
632
648
  [0.18.3]: https://github.com/DataDog/dd-trace-rb/compare/v0.18.2...v0.18.3
633
649
  [0.18.2]: https://github.com/DataDog/dd-trace-rb/compare/v0.18.1...v0.18.2
634
650
  [0.18.1]: https://github.com/DataDog/dd-trace-rb/compare/v0.18.0...v0.18.1
data/Rakefile CHANGED
@@ -46,7 +46,7 @@ namespace :spec do
46
46
  end
47
47
 
48
48
  RSpec::Core::RakeTask.new(:contrib) do |t|
49
- t.pattern = 'spec/**/contrib/{configurable,integration,patchable,patcher,registerable,configuration/*}_spec.rb'
49
+ t.pattern = 'spec/**/contrib/{configurable,integration,patchable,patcher,registerable,sampling,configuration/*}_spec.rb'
50
50
  end
51
51
 
52
52
  [
@@ -62,6 +62,7 @@ For descriptions of terminology used in APM, take a look at the [official docume
62
62
  - [Processing pipeline](#processing-pipeline)
63
63
  - [Filtering](#filtering)
64
64
  - [Processing](#processing)
65
+ - [Trace correlation](#trace-correlation)
65
66
  - [OpenTracing](#opentracing)
66
67
 
67
68
  ## Compatibility
@@ -517,6 +518,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
517
518
 
518
519
  | Key | Description | Default |
519
520
  | --- | ----------- | ------- |
521
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
520
522
  | `service_name` | Service name used for `DelayedJob` instrumentation | `'delayed_job'` |
521
523
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
522
524
 
@@ -865,6 +867,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
865
867
 
866
868
  | Key | Description | Default |
867
869
  | --- | ----------- | ------- |
870
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
868
871
  | `service_name` | Service name used for `racecar` instrumentation | `'racecar'` |
869
872
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
870
873
 
@@ -897,6 +900,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
897
900
  | --- | ----------- | ------- |
898
901
  | `application` | Your Rack application. Required for `middleware_names`. | `nil` |
899
902
  | `distributed_tracing` | Enables [distributed tracing](#distributed-tracing) so that this service trace is connected with a trace of another service if tracing headers are received | `false` |
903
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
900
904
  | `headers` | Hash of HTTP request or response headers to add as tags to the `rack.request`. Accepts `request` and `response` keys with Array values e.g. `['Last-Modified']`. Adds `http.request.headers.*` and `http.response.headers.*` tags respectively. | `{ response: ['Content-Type', 'X-Request-ID'] }` |
901
905
  | `middleware_names` | Enable this if you want to use the middleware classes as the resource names for `rack` spans. Requires `application` option to use. | `false` |
902
906
  | `quantize` | Hash containing options for quantization. May include `:query` or `:fragment`. | `{}` |
@@ -1006,6 +1010,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1006
1010
  | Key | Description | Default |
1007
1011
  | --- | ----------- | ------- |
1008
1012
  | `enabled` | Defines whether Rake tasks should be traced. Useful for temporarily disabling tracing. `true` or `false` | `true` |
1013
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
1009
1014
  | `quantize` | Hash containing options for quantization of task arguments. See below for more details and examples. | `{}` |
1010
1015
  | `service_name` | Service name used for `rake` instrumentation | `'rake'` |
1011
1016
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
@@ -1107,6 +1112,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1107
1112
 
1108
1113
  | Key | Description | Default |
1109
1114
  | --- | ----------- | ------- |
1115
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
1110
1116
  | `service_name` | Service name used for `resque` instrumentation | `'resque'` |
1111
1117
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
1112
1118
  | `workers` | An array including all worker classes you want to trace (eg `[MyJob]`) | `[]` |
@@ -1198,6 +1204,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1198
1204
 
1199
1205
  | Key | Description | Default |
1200
1206
  | --- | ----------- | ------- |
1207
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
1201
1208
  | `service_name` | Service name used for `shoryuken` instrumentation | `'shoryuken'` |
1202
1209
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
1203
1210
 
@@ -1220,6 +1227,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1220
1227
  | Key | Description | Default |
1221
1228
  | --- | ----------- | ------- |
1222
1229
  | `client_service_name` | Service name used for client-side `sidekiq` instrumentation | `'sidekiq-client'` |
1230
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
1223
1231
  | `service_name` | Service name used for server-side `sidekiq` instrumentation | `'sidekiq'` |
1224
1232
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
1225
1233
 
@@ -1271,6 +1279,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1271
1279
 
1272
1280
  | Key | Description | Default |
1273
1281
  | --- | ----------- | ------- |
1282
+ | `event_sample_rate` | Rate which spans should be sampled for search and analytics. | `nil` |
1274
1283
  | `service_name` | Service name used for `sucker_punch` instrumentation | `'sucker_punch'` |
1275
1284
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
1276
1285
 
@@ -1356,15 +1365,7 @@ The sampler can set the priority to the following values:
1356
1365
  - `Datadog::Ext::Priority::AUTO_REJECT`: the sampler automatically decided to reject the trace.
1357
1366
  - `Datadog::Ext::Priority::AUTO_KEEP`: the sampler automatically decided to keep the trace.
1358
1367
 
1359
- For now, priority sampling is disabled by default. Enabling it ensures that your sampled distributed traces will be complete. To enable the priority sampling:
1360
-
1361
- ```ruby
1362
- Datadog.configure do |c|
1363
- c.tracer priority_sampling: true
1364
- end
1365
- ```
1366
-
1367
- Once enabled, the sampler will automatically assign a priority of 0 or 1 to traces, depending on their service and volume.
1368
+ Priority sampling is enabled by default. Enabling it ensures that your sampled distributed traces will be complete. Once enabled, the sampler will automatically assign a priority of 0 or 1 to traces, depending on their service and volume.
1368
1369
 
1369
1370
  You can also set this priority manually to either drop a non-interesting trace or to keep an important one. For that, set the `context#sampling_priority` to:
1370
1371
 
@@ -1613,6 +1614,77 @@ Datadog::Pipeline.before_flush(
1613
1614
  )
1614
1615
  ```
1615
1616
 
1617
+ ### Trace correlation
1618
+
1619
+ In many cases, such as logging, it may be useful to correlate trace IDs to other events or data streams, for easier cross referencing. The tracer can produce a correlation identifier for the currently active trace via `active_correlation`, which can be used to decorate these other data sources.
1620
+
1621
+ ```ruby
1622
+ # When a trace is active...
1623
+ Datadog.tracer.trace('correlation.example') do
1624
+ # Returns #<Datadog::Correlation::Identifier>
1625
+ correlation = Datadog.tracer.active_correlation
1626
+ correlation.trace_id # => 5963550561812073440
1627
+ correlation.span_id # => 2232727802607726424
1628
+ end
1629
+
1630
+ # When a trace isn't active...
1631
+ correlation = Datadog.tracer.active_correlation
1632
+ # Returns #<Datadog::Correlation::Identifier>
1633
+ correlation = Datadog.tracer.active_correlation
1634
+ correlation.trace_id # => 0
1635
+ correlation.span_id # => 0
1636
+ ```
1637
+
1638
+ #### For logging in Ruby applications
1639
+
1640
+ To add correlation IDs to your logger, add a log formatter which retrieves the correlation IDs with `Datadog.tracer.active_correlation`, then add them to the message.
1641
+
1642
+ To properly correlate with Datadog logging, be sure the following is present:
1643
+
1644
+ - `dd.trace_id=<TRACE_ID>`: Where `<TRACE_ID>` is equal to `Datadog.tracer.active_correlation.trace_id` or `0` if no trace is active.
1645
+ - `dd.span_id=<SPAN_ID>`: Where `<SPAN_ID>` is equal to `Datadog.tracer.active_correlation.span_id` or `0` if no trace is active.
1646
+
1647
+ By default, `Datadog::Correlation::Identifier#to_s` will return `dd.trace_id=<TRACE_ID> dd.span_id=<SPAN_ID>`.
1648
+
1649
+ An example of this in practice:
1650
+
1651
+ ```ruby
1652
+ require 'ddtrace'
1653
+ require 'logger'
1654
+
1655
+ logger = Logger.new(STDOUT)
1656
+ logger.progname = 'my_app'
1657
+ logger.formatter = proc do |severity, datetime, progname, msg|
1658
+ "[#{datetime}][#{progname}][#{severity}][#{Datadog.tracer.active_correlation}] #{msg}\n"
1659
+ end
1660
+
1661
+ # When no trace is active
1662
+ logger.warn('This is an untraced operation.')
1663
+ # [2019-01-16 18:38:41 +0000][my_app][WARN][dd.trace_id=0 dd.span_id=0] This is an untraced operation.
1664
+
1665
+ # When a trace is active
1666
+ Datadog.tracer.trace('my.operation') { logger.warn('This is a traced operation.') }
1667
+ # [2019-01-16 18:38:41 +0000][my_app][WARN][dd.trace_id=8545847825299552251 dd.span_id=3711755234730770098] This is a traced operation.
1668
+ ```
1669
+
1670
+ #### For logging in Rails applications
1671
+
1672
+ Rails applications which are configured with a `ActiveSupport::TaggedLogging` logger can append correlation IDs as tags to log output. The default Rails logger implements this tagged logging, making it easier to add correlation tags.
1673
+
1674
+ In your Rails environment configuration file, add the following:
1675
+
1676
+ ```ruby
1677
+ Rails.application.configure do
1678
+ config.log_tags = [proc { Datadog.tracer.active_correlation.to_s }]
1679
+ end
1680
+
1681
+ # Web requests will produce:
1682
+ # [dd.trace_id=7110975754844687674 dd.span_id=7518426836986654206] Started GET "/articles" for 172.22.0.1 at 2019-01-16 18:50:57 +0000
1683
+ # [dd.trace_id=7110975754844687674 dd.span_id=7518426836986654206] Processing by ArticlesController#index as */*
1684
+ # [dd.trace_id=7110975754844687674 dd.span_id=7518426836986654206] Article Load (0.5ms) SELECT "articles".* FROM "articles"
1685
+ # [dd.trace_id=7110975754844687674 dd.span_id=7518426836986654206] Completed 200 OK in 7ms (Views: 5.5ms | ActiveRecord: 0.5ms)
1686
+ ```
1687
+
1616
1688
  ### OpenTracing
1617
1689
 
1618
1690
  For setting up Datadog with OpenTracing, see out [Quickstart for OpenTracing](#quickstart-for-opentracing) section for details.
@@ -9,6 +9,7 @@ module Datadog
9
9
 
10
10
  option :service_name
11
11
  option :tracer, default: Datadog.tracer
12
+ option :event_sample_rate
12
13
 
13
14
  def initialize(options = {})
14
15
  configure(options)
@@ -1,4 +1,5 @@
1
1
  require 'delayed/plugin'
2
+ require 'ddtrace/contrib/sampling'
2
3
  require 'ddtrace/contrib/delayed_job/ext'
3
4
 
4
5
  module Datadog
@@ -18,6 +19,7 @@ module Datadog
18
19
  end
19
20
 
20
21
  tracer.trace(Ext::SPAN_JOB, service: configuration[:service_name], resource: job_name) do |span|
22
+ Contrib::Sampling.set_event_sample_rate(span, configuration[:event_sample_rate])
21
23
  span.set_tag(Ext::TAG_ID, job.id)
22
24
  span.set_tag(Ext::TAG_QUEUE, job.queue) if job.queue
23
25
  span.set_tag(Ext::TAG_PRIORITY, job.priority)
@@ -1,3 +1,4 @@
1
+ require 'ddtrace/contrib/sampling'
1
2
  require 'ddtrace/contrib/active_support/notifications/event'
2
3
  require 'ddtrace/contrib/racecar/ext'
3
4
 
@@ -36,6 +37,7 @@ module Datadog
36
37
  span.service = configuration[:service_name]
37
38
  span.resource = payload[:consumer_class]
38
39
 
40
+ Contrib::Sampling.set_event_sample_rate(span, configuration[:event_sample_rate])
39
41
  span.set_tag(Ext::TAG_TOPIC, payload[:topic])
40
42
  span.set_tag(Ext::TAG_CONSUMER, payload[:consumer_class])
41
43
  span.set_tag(Ext::TAG_PARTITION, payload[:partition])
@@ -1,6 +1,7 @@
1
1
  require 'ddtrace/ext/app_types'
2
2
  require 'ddtrace/ext/http'
3
3
  require 'ddtrace/propagation/http_propagator'
4
+ require 'ddtrace/contrib/sampling'
4
5
  require 'ddtrace/contrib/rack/ext'
5
6
  require 'ddtrace/contrib/rack/request_queue'
6
7
 
@@ -25,7 +26,7 @@ module Datadog
25
26
  end
26
27
 
27
28
  def compute_queue_time(env, tracer)
28
- return unless Datadog.configuration[:rack][:request_queuing]
29
+ return unless configuration[:request_queuing]
29
30
 
30
31
  # parse the request queue time
31
32
  request_start = Datadog::Contrib::Rack::QueueTime.get_request_start(env)
@@ -34,25 +35,25 @@ module Datadog
34
35
  tracer.trace(
35
36
  Ext::SPAN_HTTP_SERVER_QUEUE,
36
37
  start_time: request_start,
37
- service: Datadog.configuration[:rack][:web_service_name]
38
+ service: configuration[:web_service_name]
38
39
  )
39
40
  end
40
41
 
41
42
  def call(env)
42
43
  # retrieve integration settings
43
- tracer = Datadog.configuration[:rack][:tracer]
44
+ tracer = configuration[:tracer]
44
45
 
45
46
  # [experimental] create a root Span to keep track of frontend web servers
46
47
  # (i.e. Apache, nginx) if the header is properly set
47
48
  frontend_span = compute_queue_time(env, tracer)
48
49
 
49
50
  trace_options = {
50
- service: Datadog.configuration[:rack][:service_name],
51
+ service: configuration[:service_name],
51
52
  resource: nil,
52
53
  span_type: Datadog::Ext::HTTP::TYPE
53
54
  }
54
55
 
55
- if Datadog.configuration[:rack][:distributed_tracing]
56
+ if configuration[:distributed_tracing]
56
57
  context = HTTPPropagator.extract(env)
57
58
  tracer.provider.context = context if context.trace_id
58
59
  end
@@ -114,7 +115,7 @@ module Datadog
114
115
  end
115
116
 
116
117
  def resource_name_for(env, status)
117
- if Datadog.configuration[:rack][:middleware_names] && env['RESPONSE_MIDDLEWARE']
118
+ if configuration[:middleware_names] && env['RESPONSE_MIDDLEWARE']
118
119
  "#{env['RESPONSE_MIDDLEWARE']}##{env['REQUEST_METHOD']}"
119
120
  else
120
121
  "#{env['REQUEST_METHOD']} #{status}".strip
@@ -138,13 +139,19 @@ module Datadog
138
139
  response_headers = parse_response_headers(headers || {})
139
140
 
140
141
  request_span.resource ||= resource_name_for(env, status)
142
+
143
+ # Set event sample rate, if available.
144
+ Contrib::Sampling.set_event_sample_rate(request_span, configuration[:event_sample_rate])
145
+
141
146
  if request_span.get_tag(Datadog::Ext::HTTP::METHOD).nil?
142
147
  request_span.set_tag(Datadog::Ext::HTTP::METHOD, env['REQUEST_METHOD'])
143
148
  end
149
+
144
150
  if request_span.get_tag(Datadog::Ext::HTTP::URL).nil?
145
- options = Datadog.configuration[:rack][:quantize]
151
+ options = configuration[:quantize]
146
152
  request_span.set_tag(Datadog::Ext::HTTP::URL, Datadog::Quantization::HTTP.url(url, options))
147
153
  end
154
+
148
155
  if request_span.get_tag(Datadog::Ext::HTTP::BASE_URL).nil?
149
156
  request_obj = ::Rack::Request.new(env)
150
157
 
@@ -157,6 +164,7 @@ module Datadog
157
164
 
158
165
  request_span.set_tag(Datadog::Ext::HTTP::BASE_URL, base_url)
159
166
  end
167
+
160
168
  if request_span.get_tag(Datadog::Ext::HTTP::STATUS_CODE).nil? && status
161
169
  request_span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, status)
162
170
  end
@@ -186,6 +194,10 @@ module Datadog
186
194
  If you need the Rack request span, try using `Datadog.tracer.active_span`.
187
195
  This key will be removed in version 1.0).freeze
188
196
 
197
+ def configuration
198
+ Datadog.configuration[:rack]
199
+ end
200
+
189
201
  def add_deprecation_warnings(env)
190
202
  env.instance_eval do
191
203
  unless instance_variable_defined?(:@patched_with_datadog_warnings)
@@ -225,7 +237,7 @@ module Datadog
225
237
 
226
238
  def parse_request_headers(env)
227
239
  {}.tap do |result|
228
- whitelist = Datadog.configuration[:rack][:headers][:request] || []
240
+ whitelist = configuration[:headers][:request] || []
229
241
  whitelist.each do |header|
230
242
  rack_header = header_to_rack_header(header)
231
243
  if env.key?(rack_header)
@@ -237,7 +249,7 @@ module Datadog
237
249
 
238
250
  def parse_response_headers(headers)
239
251
  {}.tap do |result|
240
- whitelist = Datadog.configuration[:rack][:headers][:response] || []
252
+ whitelist = configuration[:headers][:response] || []
241
253
  whitelist.each do |header|
242
254
  if headers.key?(header)
243
255
  result[Datadog::Ext::HTTP::ResponseHeaders.to_tag(header)] = headers[header]
@@ -1,3 +1,4 @@
1
+ require 'ddtrace/contrib/sampling'
1
2
  require 'ddtrace/contrib/rake/ext'
2
3
 
3
4
  module Datadog
@@ -41,6 +42,7 @@ module Datadog
41
42
 
42
43
  def annotate_invoke!(span, args)
43
44
  span.resource = name
45
+ Contrib::Sampling.set_event_sample_rate(span, configuration[:event_sample_rate])
44
46
  span.set_tag(Ext::TAG_TASK_ARG_NAMES, arg_names)
45
47
  span.set_tag(Ext::TAG_INVOKE_ARGS, quantize_args(args)) unless args.nil?
46
48
  rescue StandardError => e
@@ -19,7 +19,6 @@ module Datadog
19
19
  do_once(:resque) do
20
20
  begin
21
21
  require_relative 'resque_job'
22
- add_pin
23
22
  get_option(:workers).each { |worker| worker.extend(ResqueJob) }
24
23
  rescue StandardError => e
25
24
  Datadog::Tracer.log.error("Unable to apply Resque integration: #{e}")
@@ -27,15 +26,6 @@ module Datadog
27
26
  end
28
27
  end
29
28
 
30
- def add_pin
31
- Pin.new(
32
- get_option(:service_name),
33
- app: Ext::APP,
34
- app_type: Datadog::Ext::AppTypes::WORKER,
35
- tracer: get_option(:tracer)
36
- ).onto(::Resque)
37
- end
38
-
39
29
  def get_option(option)
40
30
  Datadog.configuration[:resque].get_option(option)
41
31
  end
@@ -1,5 +1,6 @@
1
1
  require 'ddtrace/ext/app_types'
2
2
  require 'ddtrace/sync_writer'
3
+ require 'ddtrace/contrib/sampling'
3
4
  require 'ddtrace/contrib/sidekiq/ext'
4
5
  require 'resque'
5
6
 
@@ -9,13 +10,13 @@ module Datadog
9
10
  # Uses Resque job hooks to create traces
10
11
  module ResqueJob
11
12
  def around_perform(*_)
12
- pin = Pin.get_from(::Resque)
13
- return yield unless pin && pin.tracer
14
- pin.tracer.trace(Ext::SPAN_JOB, service: pin.service) do |span|
13
+ return yield unless datadog_configuration && tracer
14
+
15
+ tracer.trace(Ext::SPAN_JOB, span_options) do |span|
15
16
  span.resource = name
16
- span.span_type = pin.app_type
17
+ span.span_type = Datadog::Ext::AppTypes::WORKER
18
+ Contrib::Sampling.set_event_sample_rate(span, datadog_configuration[:event_sample_rate])
17
19
  yield
18
- span.service = pin.service
19
20
  end
20
21
  end
21
22
 
@@ -28,8 +29,27 @@ module Datadog
28
29
  end
29
30
 
30
31
  def shutdown_tracer_when_forked!
31
- pin = Datadog::Pin.get_from(Resque)
32
- pin.tracer.shutdown! if pin && pin.tracer && pin.config && pin.config[:forked]
32
+ tracer.shutdown! if forked?
33
+ end
34
+
35
+ private
36
+
37
+ def forked?
38
+ pin = Datadog::Pin.get_from(::Resque)
39
+ return false unless pin
40
+ pin.config[:forked] == true
41
+ end
42
+
43
+ def span_options
44
+ { service: datadog_configuration[:service_name] }
45
+ end
46
+
47
+ def tracer
48
+ datadog_configuration.tracer
49
+ end
50
+
51
+ def datadog_configuration
52
+ Datadog.configuration[:resque]
33
53
  end
34
54
  end
35
55
  end
@@ -37,12 +57,17 @@ module Datadog
37
57
  end
38
58
 
39
59
  Resque.after_fork do
40
- # get the current tracer
41
- pin = Datadog::Pin.get_from(Resque)
42
- next unless pin && pin.tracer
43
- pin.config ||= {}
44
- pin.config[:forked] = true
45
-
46
- # clean the state so no CoW happens
47
- pin.tracer.provider.context = nil
60
+ configuration = Datadog.configuration[:resque]
61
+ next if configuration.nil?
62
+
63
+ # Add a pin, marking the job as forked.
64
+ # Used to trigger shutdown in forks for performance reasons.
65
+ Datadog::Pin.new(
66
+ configuration[:service_name],
67
+ config: { forked: true }
68
+ ).onto(::Resque)
69
+
70
+ # Clean the state so no CoW happens
71
+ next if configuration[:tracer].nil?
72
+ configuration[:tracer].provider.context = nil
48
73
  end
@@ -0,0 +1,14 @@
1
+ require 'ddtrace/ext/priority'
2
+
3
+ module Datadog
4
+ module Contrib
5
+ # Defines sampling behavior for integrations
6
+ module Sampling
7
+ module_function
8
+
9
+ def set_event_sample_rate(span, sample_rate)
10
+ span.set_metric(Datadog::Ext::Priority::TAG_EVENT_SAMPLE_RATE, sample_rate) unless sample_rate.nil?
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,16 +1,19 @@
1
+ require 'ddtrace/contrib/sampling'
2
+
1
3
  module Datadog
2
4
  module Contrib
3
5
  module Shoryuken
4
6
  # Tracer is a Shoryuken server-side middleware which traces executed jobs
5
7
  class Tracer
6
8
  def initialize(options = {})
7
- @tracer = options[:tracer] || Datadog.configuration[:shoryuken][:tracer]
8
- @shoryuken_service = options[:service_name] || Datadog.configuration[:shoryuken][:service_name]
9
+ @tracer = options[:tracer] || configuration[:tracer]
10
+ @shoryuken_service = options[:service_name] || configuration[:service_name]
9
11
  set_service_info(@shoryuken_service)
10
12
  end
11
13
 
12
14
  def call(worker_instance, queue, sqs_msg, body)
13
15
  @tracer.trace(Ext::SPAN_JOB, service: @shoryuken_service, span_type: Datadog::Ext::AppTypes::WORKER) do |span|
16
+ Contrib::Sampling.set_event_sample_rate(span, configuration[:event_sample_rate])
14
17
  span.resource = resource(worker_instance, body)
15
18
  span.set_tag(Ext::TAG_JOB_ID, sqs_msg.message_id)
16
19
  span.set_tag(Ext::TAG_JOB_QUEUE, queue)
@@ -31,8 +34,12 @@ module Datadog
31
34
  job_class || worker_instance.class.name
32
35
  end
33
36
 
37
+ def configuration
38
+ Datadog.configuration[:shoryuken]
39
+ end
40
+
34
41
  def set_service_info(service)
35
- return if @tracer.services[service]
42
+ return if @tracer.nil? || @tracer.services[service]
36
43
  @tracer.set_service_info(
37
44
  service,
38
45
  Ext::APP,
@@ -1,4 +1,5 @@
1
1
  require 'ddtrace/contrib/sidekiq/tracing'
2
+ require 'ddtrace/contrib/sampling'
2
3
 
3
4
  module Datadog
4
5
  module Contrib
@@ -9,19 +10,18 @@ module Datadog
9
10
 
10
11
  def initialize(options = {})
11
12
  super
12
- @sidekiq_service = options[:client_service_name] || Datadog.configuration[:sidekiq][:client_service_name]
13
+ @sidekiq_service = options[:client_service_name] || configuration[:client_service_name]
14
+ set_service_info(@sidekiq_service)
13
15
  end
14
16
 
15
17
  # Client middleware arguments are documented here:
16
18
  # https://github.com/mperham/sidekiq/wiki/Middleware#client-middleware
17
19
  def call(worker_class, job, queue, redis_pool)
18
- service = @sidekiq_service
19
- set_service_info(service)
20
-
21
20
  resource = job_resource(job)
22
21
 
23
- @tracer.trace(Ext::SPAN_PUSH, service: service) do |span|
22
+ @tracer.trace(Ext::SPAN_PUSH, service: @sidekiq_service) do |span|
24
23
  span.resource = resource
24
+ Contrib::Sampling.set_event_sample_rate(span, configuration[:event_sample_rate])
25
25
  span.set_tag(Ext::TAG_JOB_ID, job['jid'])
26
26
  span.set_tag(Ext::TAG_JOB_QUEUE, job['queue'])
27
27
  span.set_tag(Ext::TAG_JOB_WRAPPER, job['class']) if job['wrapped']
@@ -29,6 +29,12 @@ module Datadog
29
29
  yield
30
30
  end
31
31
  end
32
+
33
+ private
34
+
35
+ def configuration
36
+ Datadog.configuration[:sidekiq]
37
+ end
32
38
  end
33
39
  end
34
40
  end
@@ -1,4 +1,5 @@
1
1
  require 'ddtrace/contrib/sidekiq/tracing'
2
+ require 'ddtrace/contrib/sampling'
2
3
 
3
4
  module Datadog
4
5
  module Contrib
@@ -9,7 +10,7 @@ module Datadog
9
10
 
10
11
  def initialize(options = {})
11
12
  super
12
- @sidekiq_service = options[:service_name] || Datadog.configuration[:sidekiq][:service_name]
13
+ @sidekiq_service = options[:service_name] || configuration[:service_name]
13
14
  end
14
15
 
15
16
  def call(worker, job, queue)
@@ -20,6 +21,7 @@ module Datadog
20
21
 
21
22
  @tracer.trace(Ext::SPAN_JOB, service: service, span_type: Datadog::Ext::AppTypes::WORKER) do |span|
22
23
  span.resource = resource
24
+ Contrib::Sampling.set_event_sample_rate(span, configuration[:event_sample_rate])
23
25
  span.set_tag(Ext::TAG_JOB_ID, job['jid'])
24
26
  span.set_tag(Ext::TAG_JOB_RETRY, job['retry'])
25
27
  span.set_tag(Ext::TAG_JOB_QUEUE, job['queue'])
@@ -32,6 +34,10 @@ module Datadog
32
34
 
33
35
  private
34
36
 
37
+ def configuration
38
+ Datadog.configuration[:sidekiq]
39
+ end
40
+
35
41
  def service_from_worker_config(resource)
36
42
  # Try to get the Ruby class from the resource name.
37
43
  worker_klass = begin
@@ -1,4 +1,5 @@
1
1
  require 'sucker_punch'
2
+ require 'ddtrace/contrib/sampling'
2
3
  require 'ddtrace/contrib/sucker_punch/ext'
3
4
 
4
5
  module Datadog
@@ -18,6 +19,7 @@ module Datadog
18
19
 
19
20
  __with_instrumentation(Ext::SPAN_PERFORM) do |span|
20
21
  span.resource = "PROCESS #{self}"
22
+ Contrib::Sampling.set_event_sample_rate(span, datadog_configuration[:event_sample_rate])
21
23
  __run_perform_without_datadog(*args)
22
24
  end
23
25
  rescue => e
@@ -43,6 +45,10 @@ module Datadog
43
45
 
44
46
  private
45
47
 
48
+ def datadog_configuration
49
+ Datadog.configuration[:sucker_punch]
50
+ end
51
+
46
52
  def __with_instrumentation(name)
47
53
  pin = Datadog::Pin.get_from(::SuckerPunch)
48
54
 
@@ -0,0 +1,32 @@
1
+ module Datadog
2
+ # Contains behavior for managing correlations with tracing
3
+ # e.g. Retrieve a correlation to the current trace for logging, etc.
4
+ module Correlation
5
+ # Struct representing correlation
6
+ Identifier = Struct.new(:trace_id, :span_id).tap do |struct|
7
+ # Do this #class_eval here for Ruby 1.9.3 support.
8
+ # Ruby 2.0+ supports passing a block to Struct::new instead.
9
+ struct.class_eval do
10
+ def initialize(*args)
11
+ super
12
+ self.trace_id = trace_id || 0
13
+ self.span_id = span_id || 0
14
+ end
15
+
16
+ def to_s
17
+ "dd.trace_id=#{trace_id} dd.span_id=#{span_id}"
18
+ end
19
+ end
20
+ end.freeze
21
+
22
+ NULL_IDENTIFIER = Identifier.new.freeze
23
+
24
+ module_function
25
+
26
+ # Produces a CorrelationIdentifier from the Context provided
27
+ def identifier_from_context(context)
28
+ return NULL_IDENTIFIER if context.nil?
29
+ Identifier.new(context.trace_id, context.span_id).freeze
30
+ end
31
+ end
32
+ end
@@ -3,6 +3,8 @@ module Datadog
3
3
  # Priority is a hint given to the backend so that it knows which traces to reject or kept.
4
4
  # In a distributed context, it should be set before any context propagation (fork, RPC calls) to be effective.
5
5
  module Priority
6
+ # Tag for span sample rate; used by agent to determine whether event is emitted.
7
+ TAG_EVENT_SAMPLE_RATE = '_dd1.sr.eausr'.freeze
6
8
  # Use this to explicitely inform the backend that a trace should be rejected and not stored.
7
9
  USER_REJECT = -1
8
10
  # Used by the builtin sampler to inform the backend that a trace should be rejected and not stored.
@@ -10,6 +10,7 @@ require 'ddtrace/provider'
10
10
  require 'ddtrace/logger'
11
11
  require 'ddtrace/writer'
12
12
  require 'ddtrace/sampler'
13
+ require 'ddtrace/correlation'
13
14
 
14
15
  # \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
15
16
  module Datadog
@@ -126,7 +127,7 @@ module Datadog
126
127
 
127
128
  # Those are rare "power-user" options.
128
129
  sampler = options.fetch(:sampler, nil)
129
- priority_sampling = options[:priority_sampling]
130
+ priority_sampling = options.fetch(:priority_sampling, nil)
130
131
  max_spans_before_partial_flush = options.fetch(:max_spans_before_partial_flush, nil)
131
132
  min_spans_before_partial_flush = options.fetch(:min_spans_before_partial_flush, nil)
132
133
  partial_flush_timeout = options.fetch(:partial_flush_timeout, nil)
@@ -134,9 +135,15 @@ module Datadog
134
135
  @enabled = enabled unless enabled.nil?
135
136
  @sampler = sampler unless sampler.nil?
136
137
 
137
- if priority_sampling
138
+ # Re-build the sampler and writer if priority sampling is enabled,
139
+ # but neither are configured. Verify the sampler isn't already a
140
+ # priority sampler too, so we don't wrap one with another.
141
+ if priority_sampling != false && !@sampler.is_a?(PrioritySampler)
138
142
  @sampler = PrioritySampler.new(base_sampler: @sampler)
139
143
  @writer = Writer.new(priority_sampler: @sampler)
144
+ elsif priority_sampling == false
145
+ @sampler = sampler || Datadog::AllSampler.new if @sampler.is_a?(PrioritySampler)
146
+ @writer = Writer.new
140
147
  end
141
148
 
142
149
  @writer.transport.hostname = hostname unless hostname.nil?
@@ -351,6 +358,11 @@ module Datadog
351
358
  call_context.current_root_span
352
359
  end
353
360
 
361
+ # Return a CorrelationIdentifier for active span
362
+ def active_correlation
363
+ Datadog::Correlation.identifier_from_context(call_context)
364
+ end
365
+
354
366
  # Send the trace to the writer to enqueue the spans list in the agent
355
367
  # sending queue.
356
368
  def write(trace)
@@ -1,8 +1,8 @@
1
1
  module Datadog
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 18
5
- PATCH = 3
4
+ MINOR = 19
5
+ PATCH = 0
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
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.18.3
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-17 00:00:00.000000000 Z
11
+ date: 2019-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -449,6 +449,7 @@ files:
449
449
  - lib/ddtrace/contrib/rest_client/integration.rb
450
450
  - lib/ddtrace/contrib/rest_client/patcher.rb
451
451
  - lib/ddtrace/contrib/rest_client/request_patch.rb
452
+ - lib/ddtrace/contrib/sampling.rb
452
453
  - lib/ddtrace/contrib/sequel/configuration/settings.rb
453
454
  - lib/ddtrace/contrib/sequel/database.rb
454
455
  - lib/ddtrace/contrib/sequel/dataset.rb
@@ -482,6 +483,7 @@ files:
482
483
  - lib/ddtrace/contrib/sucker_punch/instrumentation.rb
483
484
  - lib/ddtrace/contrib/sucker_punch/integration.rb
484
485
  - lib/ddtrace/contrib/sucker_punch/patcher.rb
486
+ - lib/ddtrace/correlation.rb
485
487
  - lib/ddtrace/encoding.rb
486
488
  - lib/ddtrace/error.rb
487
489
  - lib/ddtrace/ext/app_types.rb