ddtrace 0.26.1 → 0.27.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +153 -77
  3. data/.circleci/images/primary/{Dockerfile-1.9.3 → Dockerfile-2.5.6} +8 -8
  4. data/.circleci/images/primary/Dockerfile-2.6.4 +73 -0
  5. data/.github/CODEOWNERS +1 -0
  6. data/Appraisals +201 -94
  7. data/CHANGELOG.md +25 -8
  8. data/Rakefile +153 -47
  9. data/ddtrace.gemspec +1 -1
  10. data/docker-compose.yml +56 -26
  11. data/docs/GettingStarted.md +117 -14
  12. data/lib/ddtrace.rb +4 -0
  13. data/lib/ddtrace/analytics.rb +9 -39
  14. data/lib/ddtrace/configuration.rb +0 -19
  15. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +144 -0
  16. data/lib/ddtrace/contrib/action_pack/action_controller/patcher.rb +37 -0
  17. data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +25 -0
  18. data/lib/ddtrace/contrib/action_pack/ext.rb +16 -0
  19. data/lib/ddtrace/contrib/action_pack/integration.rb +36 -0
  20. data/lib/ddtrace/contrib/action_pack/patcher.rb +29 -0
  21. data/lib/ddtrace/contrib/action_pack/utils.rb +36 -0
  22. data/lib/ddtrace/contrib/action_view/configuration/settings.rb +24 -0
  23. data/lib/ddtrace/contrib/action_view/ext.rb +17 -0
  24. data/lib/ddtrace/contrib/action_view/instrumentation.rb +192 -0
  25. data/lib/ddtrace/contrib/action_view/integration.rb +43 -0
  26. data/lib/ddtrace/contrib/action_view/patcher.rb +47 -0
  27. data/lib/ddtrace/contrib/action_view/utils.rb +32 -0
  28. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +157 -0
  29. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +62 -0
  30. data/lib/ddtrace/contrib/active_support/cache/redis.rb +47 -0
  31. data/lib/ddtrace/contrib/active_support/configuration/settings.rb +23 -0
  32. data/lib/ddtrace/contrib/active_support/ext.rb +21 -0
  33. data/lib/ddtrace/contrib/active_support/integration.rb +38 -0
  34. data/lib/ddtrace/contrib/active_support/patcher.rb +29 -0
  35. data/lib/ddtrace/contrib/ethon/configuration/settings.rb +24 -0
  36. data/lib/ddtrace/contrib/ethon/easy_patch.rb +139 -0
  37. data/lib/ddtrace/contrib/ethon/ext.rb +15 -0
  38. data/lib/ddtrace/contrib/ethon/integration.rb +35 -0
  39. data/lib/ddtrace/contrib/ethon/multi_patch.rb +80 -0
  40. data/lib/ddtrace/contrib/ethon/patcher.rb +27 -0
  41. data/lib/ddtrace/contrib/patchable.rb +1 -1
  42. data/lib/ddtrace/contrib/rails/configuration/settings.rb +43 -6
  43. data/lib/ddtrace/contrib/rails/ext.rb +0 -15
  44. data/lib/ddtrace/contrib/rails/framework.rb +37 -6
  45. data/lib/ddtrace/contrib/rails/middlewares.rb +2 -1
  46. data/lib/ddtrace/contrib/rails/patcher.rb +0 -8
  47. data/lib/ddtrace/contrib/rails/utils.rb +0 -46
  48. data/lib/ddtrace/contrib/redis/patcher.rb +12 -19
  49. data/lib/ddtrace/correlation.rb +8 -12
  50. data/lib/ddtrace/forced_tracing.rb +10 -38
  51. data/lib/ddtrace/sampler.rb +20 -74
  52. data/lib/ddtrace/span.rb +3 -4
  53. data/lib/ddtrace/tracer.rb +4 -11
  54. data/lib/ddtrace/version.rb +2 -2
  55. metadata +32 -9
  56. data/lib/ddtrace/contrib/rails/action_controller.rb +0 -100
  57. data/lib/ddtrace/contrib/rails/action_controller_patch.rb +0 -78
  58. data/lib/ddtrace/contrib/rails/action_view.rb +0 -19
  59. data/lib/ddtrace/contrib/rails/active_support.rb +0 -67
  60. data/lib/ddtrace/contrib/rails/core_extensions.rb +0 -353
@@ -26,13 +26,17 @@ To contribute, check out the [contribution guidelines][contribution docs] and [d
26
26
  - [Quickstart for OpenTracing](#quickstart-for-opentracing)
27
27
  - [Manual instrumentation](#manual-instrumentation)
28
28
  - [Integration instrumentation](#integration-instrumentation)
29
+ - [Action View](#action-view)
29
30
  - [Active Model Serializers](#active-model-serializers)
31
+ - [Action Pack](#action-pack)
30
32
  - [Active Record](#active-record)
33
+ - [Active Support](#active-support)
31
34
  - [AWS](#aws)
32
35
  - [Concurrent Ruby](#concurrent-ruby)
33
36
  - [Dalli](#dalli)
34
37
  - [DelayedJob](#delayedjob)
35
38
  - [Elastic Search](#elastic-search)
39
+ - [Ethon & Typhoeus](#ethon)
36
40
  - [Excon](#excon)
37
41
  - [Faraday](#faraday)
38
42
  - [Grape](#grape)
@@ -74,16 +78,18 @@ To contribute, check out the [contribution guidelines][contribution docs] and [d
74
78
 
75
79
  **Supported Ruby interpreters**:
76
80
 
77
- | Type | Documentation | Version | Support type |
78
- | ----- | -------------------------- | ----- | ------------ |
79
- | MRI | https://www.ruby-lang.org/ | 1.9.1 | Deprecated |
80
- | | | 1.9.3 | Deprecated |
81
- | | | 2.0 | Full |
82
- | | | 2.1 | Full |
83
- | | | 2.2 | Full |
84
- | | | 2.3 | Full |
85
- | | | 2.4 | Full |
86
- | JRuby | http://jruby.org/ | 9.1.5 | Experimental |
81
+ | Type | Documentation | Version | Support type | Gem version support | EOL Date |
82
+ | ----- | -------------------------- | ----- | ------------ | ------------------------- | ---------------- |
83
+ | MRI | https://www.ruby-lang.org/ | 1.9.1 | Maintenance | < 0.27.0 | August 6th, 2020 |
84
+ | | | 1.9.3 | Maintenance | < 0.27.0 | August 6th, 2020 |
85
+ | | | 2.0 | Full | Latest | TBD |
86
+ | | | 2.1 | Full | Latest | TBD |
87
+ | | | 2.2 | Full | Latest | TBD |
88
+ | | | 2.3 | Full | Latest | TBD |
89
+ | | | 2.4 | Full | Latest | TBD |
90
+ | | | 2.5 | Full | Latest | TBD |
91
+ | | | 2.6 | Full | Latest | TBD |
92
+ | JRuby | http://jruby.org/ | 9.1.5 | Experimental | Latest | TBD |
87
93
 
88
94
  **Supported web servers**:
89
95
 
@@ -105,6 +111,10 @@ To contribute, check out the [contribution guidelines][contribution docs] and [d
105
111
 
106
112
  *Deprecated* indicates support will be removed in a future release.
107
113
 
114
+ *Maintenance* indicates only critical bugfixes are backported until EOL.
115
+
116
+ *EOL* indicates support is no longer provided.
117
+
108
118
  ## Installation
109
119
 
110
120
  The following steps will help you quickly start tracing your Ruby application.
@@ -316,13 +326,17 @@ For a list of available integrations, and their configuration options, please re
316
326
 
317
327
  | Name | Key | Versions Supported | How to configure | Gem source |
318
328
  | ------------------------ | -------------------------- | ------------------------ | ----------------------------------- | ------------------------------------------------------------------------------ |
329
+ | Action View | `action_view` | `>= 3.2, < 6.0` | *[Link](#action-view)* | *[Link](https://github.com/rails/rails/tree/master/actionview)* |
319
330
  | Active Model Serializers | `active_model_serializers` | `>= 0.9` | *[Link](#active-model-serializers)* | *[Link](https://github.com/rails-api/active_model_serializers)* |
331
+ | Action Pack | `action_pack` | `>= 3.2, < 6.0` | *[Link](#action-pack)* | *[Link](https://github.com/rails/rails/tree/master/actionpack)* |
320
332
  | Active Record | `active_record` | `>= 3.2, < 6.0` | *[Link](#active-record)* | *[Link](https://github.com/rails/rails/tree/master/activerecord)* |
333
+ | Active Support | `active_support` | `>= 3.2, < 6.0` | *[Link](#active-support)* | *[Link](https://github.com/rails/rails/tree/master/activesupport)* |
321
334
  | AWS | `aws` | `>= 2.0` | *[Link](#aws)* | *[Link](https://github.com/aws/aws-sdk-ruby)* |
322
335
  | Concurrent Ruby | `concurrent_ruby` | `>= 0.9` | *[Link](#concurrent-ruby)* | *[Link](https://github.com/ruby-concurrency/concurrent-ruby)* |
323
336
  | Dalli | `dalli` | `>= 2.7` | *[Link](#dalli)* | *[Link](https://github.com/petergoldstein/dalli)* |
324
337
  | DelayedJob | `delayed_job` | `>= 4.1` | *[Link](#delayedjob)* | *[Link](https://github.com/collectiveidea/delayed_job)* |
325
338
  | Elastic Search | `elasticsearch` | `>= 6.0` | *[Link](#elastic-search)* | *[Link](https://github.com/elastic/elasticsearch-ruby)* |
339
+ | Ethon | `ethon` | `>= 0.11.0` | *[Link](#ethon)* | *[Link](https://github.com/typhoeus/ethon)* |
326
340
  | Excon | `excon` | `>= 0.62` | *[Link](#excon)* | *[Link](https://github.com/excon/excon)* |
327
341
  | Faraday | `faraday` | `>= 0.14` | *[Link](#faraday)* | *[Link](https://github.com/lostisland/faraday)* |
328
342
  | Grape | `grape` | `>= 1.0` | *[Link](#grape)* | *[Link](https://github.com/ruby-grape/grape)* |
@@ -333,17 +347,39 @@ For a list of available integrations, and their configuration options, please re
333
347
  | Net/HTTP | `http` | *(Any supported Ruby)* | *[Link](#nethttp)* | *[Link](https://ruby-doc.org/stdlib-2.4.0/libdoc/net/http/rdoc/Net/HTTP.html)* |
334
348
  | Racecar | `racecar` | `>= 0.3.5` | *[Link](#racecar)* | *[Link](https://github.com/zendesk/racecar)* |
335
349
  | Rack | `rack` | `>= 1.4.7` | *[Link](#rack)* | *[Link](https://github.com/rack/rack)* |
336
- | Rails | `rails` | `>= 3.2, <= 6.0` | *[Link](#rails)* | *[Link](https://github.com/rails/rails)* |
350
+ | Rails | `rails` | `>= 3.2, < 6.0` | *[Link](#rails)* | *[Link](https://github.com/rails/rails)* |
337
351
  | Rake | `rake` | `>= 12.0` | *[Link](#rake)* | *[Link](https://github.com/ruby/rake)* |
338
352
  | Redis | `redis` | `>= 3.2, < 4.0` | *[Link](#redis)* | *[Link](https://github.com/redis/redis-rb)* |
339
353
  | Resque | `resque` | `>= 1.0, < 2.0` | *[Link](#resque)* | *[Link](https://github.com/resque/resque)* |
340
354
  | Rest Client | `rest-client` | `>= 1.8` | *[Link](#rest-client)* | *[Link](https://github.com/rest-client/rest-client)* |
341
355
  | Sequel | `sequel` | `>= 3.41` | *[Link](#sequel)* | *[Link](https://github.com/jeremyevans/sequel)* |
342
- | Shoryuken | `shoryuken` | `>= 4.0.2` | *[Link](#shoryuken)* | *[Link](https://github.com/phstc/shoryuken)*
356
+ | Shoryuken | `shoryuken` | `>= 4.0.2` | *[Link](#shoryuken)* | *[Link](https://github.com/phstc/shoryuken)* |
343
357
  | Sidekiq | `sidekiq` | `>= 3.5.4` | *[Link](#sidekiq)* | *[Link](https://github.com/mperham/sidekiq)* |
344
358
  | Sinatra | `sinatra` | `>= 1.4.5` | *[Link](#sinatra)* | *[Link](https://github.com/sinatra/sinatra)* |
345
359
  | Sucker Punch | `sucker_punch` | `>= 2.0` | *[Link](#sucker-punch)* | *[Link](https://github.com/brandonhilkert/sucker_punch)* |
346
360
 
361
+ ### Action View
362
+
363
+ Most of the time, Active Support is set up as part of Rails, but it can be activated separately:
364
+
365
+ ```ruby
366
+ require 'actionview'
367
+ require 'ddtrace'
368
+
369
+ Datadog.configure do |c|
370
+ c.use :action_view, options
371
+ end
372
+ ```
373
+
374
+ Where `options` is an optional `Hash` that accepts the following parameters:
375
+
376
+ | Key | Description | Default |
377
+ | ---| --- | --- |
378
+ | `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
379
+ | `service_name` | Service name used for rendering instrumentation. | `action_view` |
380
+ | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
381
+ | `template_base_path` | Used when the template name is parsed. If you don't store your templates in the `views/` folder, you may need to change this value | `'views/'` |
382
+
347
383
  ### Active Model Serializers
348
384
 
349
385
  The Active Model Serializers integration traces the `serialize` event for version 0.9+ and the `render` event for version 0.10+.
@@ -366,6 +402,27 @@ ActiveModelSerializers::SerializableResource.new(test_obj).serializable_hash
366
402
  | `service_name` | Service name used for `active_model_serializers` instrumentation. | `'active_model_serializers'` |
367
403
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
368
404
 
405
+ ### Action Pack
406
+
407
+ Most of the time, Action Pack is set up as part of Rails, but it can be activated separately:
408
+
409
+ ```ruby
410
+ require 'actionpack'
411
+ require 'ddtrace'
412
+
413
+ Datadog.configure do |c|
414
+ c.use :action_pack, options
415
+ end
416
+ ```
417
+
418
+ Where `options` is an optional `Hash` that accepts the following parameters:
419
+
420
+ | Key | Description | Default |
421
+ | ---| --- | --- |
422
+ | `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
423
+ | `service_name` | Service name used for rendering instrumentation. | `action_pack` |
424
+ | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
425
+
369
426
  ### Active Record
370
427
 
371
428
  Most of the time, Active Record is set up as part of a web framework (Rails, Sinatra...) however, it can be set up alone:
@@ -434,6 +491,30 @@ end
434
491
 
435
492
  If ActiveRecord traces an event that uses a connection that matches a key defined by `describes`, it will use the trace settings assigned to that connection. If the connection does not match any of the described connections, it will use default settings defined by `c.use :active_record` instead.
436
493
 
494
+ ### Active Support
495
+
496
+ Most of the time, Active Support is set up as part of Rails, but it can be activated separately:
497
+
498
+ ```ruby
499
+ require 'activesupport'
500
+ require 'ddtrace'
501
+
502
+ Datadog.configure do |c|
503
+ c.use :active_support, options
504
+ end
505
+
506
+ cache = ActiveSupport::Cache::MemoryStore.new
507
+ cache.read('city')
508
+ ```
509
+
510
+ Where `options` is an optional `Hash` that accepts the following parameters:
511
+
512
+ | Key | Description | Default |
513
+ | ---| --- | --- |
514
+ | `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
515
+ | `cache_service` | Service name used for caching with `active_support` instrumentation. | `active_support-cache` |
516
+ | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
517
+
437
518
  ### AWS
438
519
 
439
520
  The AWS integration will trace every interaction (e.g. API calls) with AWS services (S3, ElastiCache etc.).
@@ -559,6 +640,27 @@ Where `options` is an optional `Hash` that accepts the following parameters:
559
640
  | `service_name` | Service name used for `elasticsearch` instrumentation | `'elasticsearch'` |
560
641
  | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
561
642
 
643
+ ### Ethon
644
+
645
+ The `ethon` integration will trace any HTTP request through `Easy` or `Multi` objects. Note that this integration also supports `Typhoeus` library which is based on `Ethon`.
646
+
647
+ ```ruby
648
+ require 'ddtrace'
649
+
650
+ Datadog.configure do |c|
651
+ c.use :ethon, options
652
+ end
653
+ ```
654
+
655
+ Where `options` is an optional `Hash` that accepts the following parameters:
656
+
657
+ | Key | Description | Default |
658
+ | --- | ----------- | ------- |
659
+ | `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
660
+ | `distributed_tracing` | Enables [distributed tracing](#distributed-tracing) | `true` |
661
+ | `service_name` | Service name for `ethon` instrumentation. | `'ethon'` |
662
+ | `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
663
+
562
664
  ### Excon
563
665
 
564
666
  The `excon` integration is available through the `ddtrace` middleware:
@@ -1000,10 +1102,11 @@ Where `options` is an optional `Hash` that accepts the following parameters:
1000
1102
 
1001
1103
  | Ruby Versions | Supported Rails Versions |
1002
1104
  | ------------- | ------------------------ |
1003
- | 1.9.3 - 2.0 | 3.0 - 3.2 |
1105
+ | 2.0 | 3.0 - 3.2 |
1004
1106
  | 2.1 | 3.0 - 4.2 |
1005
1107
  | 2.2 - 2.3 | 3.0 - 5.2 |
1006
1108
  | 2.4 - 2.5 | 4.2.8 - 5.2 |
1109
+ | 2.6 | 5.0 - 5.2 |
1007
1110
 
1008
1111
  ### Rake
1009
1112
 
@@ -1499,7 +1602,7 @@ Service B:
1499
1602
  Priority: 1
1500
1603
 
1501
1604
  |
1502
- | Service B HTTP Request:
1605
+ | Service C HTTP Request:
1503
1606
  | Headers:
1504
1607
  | x-datadog-trace-id: 100000000000000001
1505
1608
  | x-datadog-parent-id: 100000000000000456
data/lib/ddtrace.rb CHANGED
@@ -21,13 +21,17 @@ module Datadog
21
21
  extend Contrib::Extensions
22
22
  end
23
23
 
24
+ require 'ddtrace/contrib/action_pack/integration'
25
+ require 'ddtrace/contrib/action_view/integration'
24
26
  require 'ddtrace/contrib/active_model_serializers/integration'
25
27
  require 'ddtrace/contrib/active_record/integration'
28
+ require 'ddtrace/contrib/active_support/integration'
26
29
  require 'ddtrace/contrib/aws/integration'
27
30
  require 'ddtrace/contrib/concurrent_ruby/integration'
28
31
  require 'ddtrace/contrib/dalli/integration'
29
32
  require 'ddtrace/contrib/delayed_job/integration'
30
33
  require 'ddtrace/contrib/elasticsearch/integration'
34
+ require 'ddtrace/contrib/ethon/integration'
31
35
  require 'ddtrace/contrib/excon/integration'
32
36
  require 'ddtrace/contrib/faraday/integration'
33
37
  require 'ddtrace/contrib/grape/integration'
@@ -12,46 +12,16 @@ module Datadog
12
12
 
13
13
  # Extension for Datadog::Span
14
14
  module Span
15
- def self.included(base)
16
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
17
- base.class_eval do
18
- # Instance methods
19
- include InstanceMethodsCompatibility
20
- include InstanceMethods
21
- end
15
+ def set_tag(key, value)
16
+ case key
17
+ when Ext::Analytics::TAG_ENABLED
18
+ # If true, set rate to 1.0, otherwise set 0.0.
19
+ value = value == true ? Ext::Analytics::DEFAULT_SAMPLE_RATE : 0.0
20
+ Analytics.set_sample_rate(self, value)
21
+ when Ext::Analytics::TAG_SAMPLE_RATE
22
+ Analytics.set_sample_rate(self, value)
22
23
  else
23
- base.send(:prepend, InstanceMethods)
24
- end
25
- end
26
-
27
- # Compatibility shim for Rubies not supporting `.prepend`
28
- module InstanceMethodsCompatibility
29
- def self.included(base)
30
- base.class_eval do
31
- alias_method :set_tag_without_analytics, :set_tag
32
- # DEV: When we stack multiple extensions the method might already be removed
33
- remove_method :set_tag if method_defined?(:set_tag)
34
- end
35
- end
36
-
37
- def set_tag(*args, &block)
38
- set_tag_without_analytics(*args, &block)
39
- end
40
- end
41
-
42
- # Instance methods
43
- module InstanceMethods
44
- def set_tag(key, value)
45
- case key
46
- when Ext::Analytics::TAG_ENABLED
47
- # If true, set rate to 1.0, otherwise set 0.0.
48
- value = value == true ? Ext::Analytics::DEFAULT_SAMPLE_RATE : 0.0
49
- Analytics.set_sample_rate(self, value)
50
- when Ext::Analytics::TAG_SAMPLE_RATE
51
- Analytics.set_sample_rate(self, value)
52
- else
53
- super if defined?(super)
54
- end
24
+ super if defined?(super)
55
25
  end
56
26
  end
57
27
  end
@@ -6,11 +6,6 @@ module Datadog
6
6
  module Configuration
7
7
  attr_writer :configuration
8
8
 
9
- RUBY_19_DEPRECATION_WARNING = %(
10
- Support for Ruby versions < 2.0 in dd-trace-rb is DEPRECATED.
11
- Last version to support Ruby < 2.0 will be 0.26.x, which will only receive critical bugfixes to existing features.
12
- Support for Ruby versions < 2.0 will be REMOVED with version 0.27.0.).freeze
13
-
14
9
  def configuration
15
10
  @configuration ||= Settings.new
16
11
  end
@@ -21,9 +16,6 @@ module Datadog
21
16
  else
22
17
  PinSetup.new(target, opts).call
23
18
  end
24
-
25
- # Raise Ruby 1.9 deprecation warning, if necessary.
26
- raise_ruby_19_deprecation_warning!
27
19
  end
28
20
 
29
21
  # Helper methods
@@ -34,16 +26,5 @@ module Datadog
34
26
  def runtime_metrics
35
27
  tracer.writer.runtime_metrics
36
28
  end
37
-
38
- # TODO: Remove with version 0.27.0
39
- def raise_ruby_19_deprecation_warning!
40
- return unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
41
-
42
- require 'ddtrace/patcher'
43
-
44
- Datadog::Patcher.do_once(:ruby_19_deprecation_warning) do
45
- Datadog::Tracer.log.warn(RUBY_19_DEPRECATION_WARNING)
46
- end
47
- end
48
29
  end
49
30
  end
@@ -0,0 +1,144 @@
1
+ require 'ddtrace/ext/http'
2
+
3
+ require 'ddtrace/contrib/action_pack/ext'
4
+ require 'ddtrace/contrib/action_pack/utils'
5
+ require 'ddtrace/contrib/rack/middlewares'
6
+
7
+ module Datadog
8
+ module Contrib
9
+ module ActionPack
10
+ module ActionController
11
+ # Instrumentation for ActionController components
12
+ module Instrumentation
13
+ module_function
14
+
15
+ def start_processing(payload)
16
+ # trace the execution
17
+ tracer = Datadog.configuration[:action_pack][:tracer]
18
+ service = Datadog.configuration[:action_pack][:controller_service]
19
+ type = Datadog::Ext::HTTP::TYPE_INBOUND
20
+ span = tracer.trace(Ext::SPAN_ACTION_CONTROLLER, service: service, span_type: type)
21
+
22
+ # attach the current span to the tracing context
23
+ tracing_context = payload.fetch(:tracing_context)
24
+ tracing_context[:dd_request_span] = span
25
+ rescue StandardError => e
26
+ Datadog::Tracer.log.error(e.message)
27
+ end
28
+
29
+ def finish_processing(payload)
30
+ # retrieve the tracing context and the latest active span
31
+ tracing_context = payload.fetch(:tracing_context)
32
+ env = payload.fetch(:env)
33
+ span = tracing_context[:dd_request_span]
34
+ return unless span && !span.finished?
35
+
36
+ begin
37
+ # Set the resource name, if it's still the default name
38
+ if span.resource == span.name
39
+ span.resource = "#{payload.fetch(:controller)}##{payload.fetch(:action)}"
40
+ end
41
+
42
+ # Set the resource name of the Rack request span unless this is an exception controller.
43
+ unless exception_controller?(payload)
44
+ rack_request_span = env[Datadog::Contrib::Rack::TraceMiddleware::RACK_REQUEST_SPAN]
45
+ rack_request_span.resource = span.resource if rack_request_span
46
+ end
47
+
48
+ # Set analytics sample rate
49
+ Utils.set_analytics_sample_rate(span)
50
+
51
+ # Associate with runtime metrics
52
+ Datadog.runtime_metrics.associate_with_span(span)
53
+
54
+ span.set_tag(Ext::TAG_ROUTE_ACTION, payload.fetch(:action))
55
+ span.set_tag(Ext::TAG_ROUTE_CONTROLLER, payload.fetch(:controller))
56
+
57
+ exception = payload[:exception_object]
58
+ if exception.nil?
59
+ # [christian] in some cases :status is not defined,
60
+ # rather than firing an error, simply acknowledge we don't know it.
61
+ status = payload.fetch(:status, '?').to_s
62
+ span.status = 1 if status.starts_with?('5')
63
+ elsif Utils.exception_is_error?(exception)
64
+ span.set_error(exception)
65
+ end
66
+ ensure
67
+ span.finish
68
+ end
69
+ rescue StandardError => e
70
+ Datadog::Tracer.log.error(e.message)
71
+ end
72
+
73
+ def exception_controller?(payload)
74
+ exception_controller_class = Datadog.configuration[:action_pack][:exception_controller]
75
+ controller = payload.fetch(:controller)
76
+ headers = payload.fetch(:headers)
77
+
78
+ # If no exception controller class has been set,
79
+ # guess whether this is an exception controller from the headers.
80
+ if exception_controller_class.nil?
81
+ !headers[:request_exception].nil?
82
+ # If an exception controller class has been specified,
83
+ # check if the controller is a kind of the exception controller class.
84
+ elsif exception_controller_class.is_a?(Class) || exception_controller_class.is_a?(Module)
85
+ controller <= exception_controller_class
86
+ # Otherwise if the exception controller class is some other value (like false)
87
+ # assume that this controller doesn't handle exceptions.
88
+ else
89
+ false
90
+ end
91
+ end
92
+
93
+ # Instrumentation for ActionController::Metal
94
+ module Metal
95
+ def process_action(*args)
96
+ # mutable payload with a tracing context that is used in two different
97
+ # signals; it propagates the request span so that it can be finished
98
+ # no matter what
99
+ payload = {
100
+ controller: self.class,
101
+ action: action_name,
102
+ env: request.env,
103
+ headers: {
104
+ # The exception this controller was given in the request,
105
+ # which is typical if the controller is configured to handle exceptions.
106
+ request_exception: request.headers['action_dispatch.exception']
107
+ },
108
+ tracing_context: {}
109
+ }
110
+
111
+ begin
112
+ # process and catch request exceptions
113
+ Instrumentation.start_processing(payload)
114
+ result = super(*args)
115
+ status = datadog_response_status
116
+ payload[:status] = status unless status.nil?
117
+ result
118
+ # rubocop:disable Lint/RescueException
119
+ rescue Exception => e
120
+ payload[:exception] = [e.class.name, e.message]
121
+ payload[:exception_object] = e
122
+ raise e
123
+ end
124
+ # rubocop:enable Lint/RescueException
125
+ ensure
126
+ Instrumentation.finish_processing(payload)
127
+ end
128
+
129
+ def datadog_response_status
130
+ case response
131
+ when ::ActionDispatch::Response
132
+ response.status
133
+ when Array
134
+ # Likely a Rack response array: first element is the status.
135
+ status = response.first
136
+ status.class <= Integer ? status : nil
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end