ddtrace 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -2
- data/Rakefile +9 -1
- data/ddtrace.gemspec +2 -0
- data/docs/GettingStarted.md +72 -4
- data/lib/ddtrace/contrib/rack/patcher.rb +2 -1
- data/lib/ddtrace/contrib/rails/patcher.rb +39 -3
- data/lib/ddtrace/contrib/rails/railtie.rb +8 -5
- data/lib/ddtrace/opentracer.rb +40 -0
- data/lib/ddtrace/opentracer/binary_propagator.rb +24 -0
- data/lib/ddtrace/opentracer/carrier.rb +6 -0
- data/lib/ddtrace/opentracer/distributed_headers.rb +46 -0
- data/lib/ddtrace/opentracer/global_tracer.rb +15 -0
- data/lib/ddtrace/opentracer/propagator.rb +22 -0
- data/lib/ddtrace/opentracer/rack_propagator.rb +60 -0
- data/lib/ddtrace/opentracer/scope.rb +15 -0
- data/lib/ddtrace/opentracer/scope_manager.rb +6 -0
- data/lib/ddtrace/opentracer/span.rb +90 -0
- data/lib/ddtrace/opentracer/span_context.rb +14 -0
- data/lib/ddtrace/opentracer/span_context_factory.rb +23 -0
- data/lib/ddtrace/opentracer/text_map_propagator.rb +73 -0
- data/lib/ddtrace/opentracer/thread_local_scope.rb +30 -0
- data/lib/ddtrace/opentracer/thread_local_scope_manager.rb +40 -0
- data/lib/ddtrace/opentracer/tracer.rb +208 -0
- data/lib/ddtrace/version.rb +1 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4c07e2d55c825aa80fda2d80abd0be7bce884c47a869d54fc5ca32f4e60653e
|
4
|
+
data.tar.gz: a58bd25922fa32c3c921395a9a00b37e5b0941399f3a48cf15735ef11935808f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd1c737a23055b67ccd2a0c081bfd64cd6156d744ca9c6b982623406b04be282de3c7b0328757dafef0bd9916f822c8a59a742be37f04f3225e192574fd7f0b9
|
7
|
+
data.tar.gz: 9418e24136ab3721c4404cce92dbf637d86139b5d574356e6918a5cf618de2a881add70f1420ca419afe6a751b1fd9a58871e780d22294187a5327787e5ebba4
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,17 @@
|
|
4
4
|
|
5
5
|
## [Unreleased (beta)]
|
6
6
|
|
7
|
+
## [0.16.0] - 2018-09-18
|
8
|
+
|
9
|
+
Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.16.0
|
10
|
+
|
11
|
+
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.15.0...v0.16.0
|
12
|
+
|
13
|
+
### Added
|
14
|
+
|
15
|
+
- OpenTracing support (#517)
|
16
|
+
- `middleware` option for disabling Rails trace middleware. (#552)
|
17
|
+
|
7
18
|
## [0.15.0] - 2018-09-12
|
8
19
|
|
9
20
|
Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.15.0
|
@@ -500,8 +511,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
500
511
|
|
501
512
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
502
513
|
|
503
|
-
[Unreleased (stable)]: https://github.com/DataDog/dd-trace-rb/compare/v0.
|
504
|
-
[Unreleased (beta)]: https://github.com/DataDog/dd-trace-rb/compare/v0.
|
514
|
+
[Unreleased (stable)]: https://github.com/DataDog/dd-trace-rb/compare/v0.16.0...master
|
515
|
+
[Unreleased (beta)]: https://github.com/DataDog/dd-trace-rb/compare/v0.16.0...0.17-dev
|
516
|
+
[0.15.0]: https://github.com/DataDog/dd-trace-rb/compare/v0.15.0...v0.16.0
|
505
517
|
[0.15.0]: https://github.com/DataDog/dd-trace-rb/compare/v0.14.2...v0.15.0
|
506
518
|
[0.14.2]: https://github.com/DataDog/dd-trace-rb/compare/v0.14.1...v0.14.2
|
507
519
|
[0.14.1]: https://github.com/DataDog/dd-trace-rb/compare/v0.14.0...v0.14.1
|
data/Rakefile
CHANGED
@@ -15,7 +15,11 @@ namespace :spec do
|
|
15
15
|
|
16
16
|
RSpec::Core::RakeTask.new(:main) do |t|
|
17
17
|
t.pattern = 'spec/**/*_spec.rb'
|
18
|
-
t.exclude_pattern = 'spec/**/{contrib,benchmark,redis}/**/*_spec.rb'
|
18
|
+
t.exclude_pattern = 'spec/**/{contrib,benchmark,redis,opentracer}/**/*_spec.rb'
|
19
|
+
end
|
20
|
+
|
21
|
+
RSpec::Core::RakeTask.new(:opentracer) do |t|
|
22
|
+
t.pattern = 'spec/ddtrace/opentracer/**/*_spec.rb'
|
19
23
|
end
|
20
24
|
|
21
25
|
RSpec::Core::RakeTask.new(:rails) do |t|
|
@@ -311,6 +315,7 @@ task :ci do
|
|
311
315
|
sh 'bundle exec rake test:main'
|
312
316
|
sh 'bundle exec rake spec:main'
|
313
317
|
sh 'bundle exec rake spec:contrib'
|
318
|
+
sh 'bundle exec rake spec:opentracer'
|
314
319
|
|
315
320
|
if RUBY_PLATFORM != 'java'
|
316
321
|
# Contrib minitests
|
@@ -366,6 +371,7 @@ task :ci do
|
|
366
371
|
sh 'bundle exec rake test:main'
|
367
372
|
sh 'bundle exec rake spec:main'
|
368
373
|
sh 'bundle exec rake spec:contrib'
|
374
|
+
sh 'bundle exec rake spec:opentracer'
|
369
375
|
|
370
376
|
if RUBY_PLATFORM != 'java'
|
371
377
|
# Contrib minitests
|
@@ -432,6 +438,7 @@ task :ci do
|
|
432
438
|
sh 'bundle exec rake test:main'
|
433
439
|
sh 'bundle exec rake spec:main'
|
434
440
|
sh 'bundle exec rake spec:contrib'
|
441
|
+
sh 'bundle exec rake spec:opentracer'
|
435
442
|
|
436
443
|
if RUBY_PLATFORM != 'java'
|
437
444
|
# Contrib minitests
|
@@ -497,6 +504,7 @@ task :ci do
|
|
497
504
|
sh 'bundle exec rake test:main'
|
498
505
|
sh 'bundle exec rake spec:main'
|
499
506
|
sh 'bundle exec rake spec:contrib'
|
507
|
+
sh 'bundle exec rake spec:opentracer'
|
500
508
|
|
501
509
|
if RUBY_PLATFORM != 'java'
|
502
510
|
# Contrib minitests
|
data/ddtrace.gemspec
CHANGED
@@ -33,6 +33,8 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.require_paths = ['lib']
|
34
34
|
|
35
35
|
spec.add_dependency 'msgpack'
|
36
|
+
# TODO: Move this to Appraisals?
|
37
|
+
spec.add_dependency 'opentracing', '>= 0.4.1'
|
36
38
|
|
37
39
|
spec.add_development_dependency 'rake', '>= 10.5'
|
38
40
|
spec.add_development_dependency 'rubocop', '= 0.49.1' if RUBY_VERSION >= '2.1.0'
|
data/docs/GettingStarted.md
CHANGED
@@ -21,6 +21,7 @@ For descriptions of terminology used in APM, take a look at the [official docume
|
|
21
21
|
- [Installation](#installation)
|
22
22
|
- [Quickstart for Rails applications](#quickstart-for-rails-applications)
|
23
23
|
- [Quickstart for Ruby applications](#quickstart-for-ruby-applications)
|
24
|
+
- [Quickstart for OpenTracing](#quickstart-for-opentracing)
|
24
25
|
- [Manual instrumentation](#manual-instrumentation)
|
25
26
|
- [Integration instrumentation](#integration-instrumentation)
|
26
27
|
- [Active Record](#active-record)
|
@@ -59,6 +60,7 @@ For descriptions of terminology used in APM, take a look at the [official docume
|
|
59
60
|
- [Processing pipeline](#processing-pipeline)
|
60
61
|
- [Filtering](#filtering)
|
61
62
|
- [Processing](#processing)
|
63
|
+
- [OpenTracing](#opentracing)
|
62
64
|
|
63
65
|
## Compatibility
|
64
66
|
|
@@ -75,10 +77,6 @@ For descriptions of terminology used in APM, take a look at the [official docume
|
|
75
77
|
| | | 2.4 | Full |
|
76
78
|
| JRuby | http://jruby.org/ | 9.1.5 | Experimental |
|
77
79
|
|
78
|
-
*Full* support indicates all tracer features are available.
|
79
|
-
|
80
|
-
*Experimental* indicates most features should be available, but unverified.
|
81
|
-
|
82
80
|
**Supported web servers**:
|
83
81
|
|
84
82
|
| Type | Documentation | Version | Support type |
|
@@ -87,6 +85,16 @@ For descriptions of terminology used in APM, take a look at the [official docume
|
|
87
85
|
| Unicorn | https://bogomips.org/unicorn/ | 4.8+ / 5.1+ | Full |
|
88
86
|
| Passenger | https://www.phusionpassenger.com/ | 5.0+ | Full |
|
89
87
|
|
88
|
+
**Supported tracing frameworks**:
|
89
|
+
|
90
|
+
| Type | Documentation | Version | Support type |
|
91
|
+
| ----------- | ----------------------------------------------- | --------------------- | ------------ |
|
92
|
+
| OpenTracing | https://github.com/opentracing/opentracing-ruby | 0.4.1+ (w/ Ruby 2.1+) | Experimental |
|
93
|
+
|
94
|
+
*Full* support indicates all tracer features are available.
|
95
|
+
|
96
|
+
*Experimental* indicates most features should be available, but unverified.
|
97
|
+
|
90
98
|
## Installation
|
91
99
|
|
92
100
|
The following steps will help you quickly start tracing your Ruby application.
|
@@ -136,6 +144,36 @@ The Ruby APM tracer sends trace data through the Datadog Agent.
|
|
136
144
|
1. Activate integration instrumentation (see [Integration instrumentation](#integration-instrumentation))
|
137
145
|
2. Add manual instrumentation around your code (see [Manual instrumentation](#manual-instrumentation))
|
138
146
|
|
147
|
+
### Quickstart for OpenTracing
|
148
|
+
|
149
|
+
1. Install the gem with `gem install ddtrace`
|
150
|
+
2. To your OpenTracing configuration file, add the following:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
require 'opentracing'
|
154
|
+
require 'ddtrace'
|
155
|
+
require 'ddtrace/opentracer'
|
156
|
+
|
157
|
+
# Activate the Datadog tracer for OpenTracing
|
158
|
+
OpenTracing.global_tracer = Datadog::OpenTracer::Tracer.new
|
159
|
+
```
|
160
|
+
|
161
|
+
3. (Optional) Add a configuration block to your Ruby application to configure Datadog with:
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
Datadog.configure do |c|
|
165
|
+
# Configure the Datadog tracer here.
|
166
|
+
# Activate integrations, change tracer settings, etc...
|
167
|
+
# By default without additional configuration,
|
168
|
+
# no additional integrations will be traced, only
|
169
|
+
# what you have instrumented with OpenTracing.
|
170
|
+
end
|
171
|
+
```
|
172
|
+
|
173
|
+
4. (Optional) Add or activate additional instrumentation by doing either of the following:
|
174
|
+
1. Activate Datadog integration instrumentation (see [Integration instrumentation](#integration-instrumentation))
|
175
|
+
2. Add Datadog manual instrumentation around your code (see [Manual instrumentation](#manual-instrumentation))
|
176
|
+
|
139
177
|
### Final steps for installation
|
140
178
|
|
141
179
|
After setting up, your services will appear on the [APM services page](https://app.datadoghq.com/apm/services) within a few minutes. Learn more about [using the APM UI][visualization docs].
|
@@ -869,6 +907,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
|
|
869
907
|
| ``database_service`` | Database service name used when tracing database activity | ``<app_name>-<adapter_name>`` |
|
870
908
|
| ``exception_controller`` | Class or Module which identifies a custom exception controller class. Tracer provides improved error behavior when it can identify custom exception controllers. By default, without this option, it 'guesses' what a custom exception controller looks like. Providing this option aids this identification. | ``nil`` |
|
871
909
|
| ``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` |
|
910
|
+
| ``middleware`` | Add the trace middleware to the Rails application. Set to `false` if you don't want the middleware to load. | `true` |
|
872
911
|
| ``middleware_names`` | Enables any short-circuited middleware requests to display the middleware name as resource for the trace. | `false` |
|
873
912
|
| ``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/`` |
|
874
913
|
| ``tracer`` | A ``Datadog::Tracer`` instance used to instrument the application. Usually you don't need to set that. | ``Datadog.tracer`` |
|
@@ -1510,3 +1549,32 @@ Datadog::Pipeline.before_flush(
|
|
1510
1549
|
Datadog::Pipeline::SpanProcessor.new { |span| span.resource.gsub!(/password=.*/, '') }
|
1511
1550
|
)
|
1512
1551
|
```
|
1552
|
+
|
1553
|
+
### OpenTracing
|
1554
|
+
|
1555
|
+
For setting up Datadog with OpenTracing, see out [Quickstart for OpenTracing](#quickstart-for-opentracing) section for details.
|
1556
|
+
|
1557
|
+
**Configuring Datadog tracer settings**
|
1558
|
+
|
1559
|
+
The underlying Datadog tracer can be configured by passing options (which match `Datadog::Tracer`) when configuring the global tracer:
|
1560
|
+
|
1561
|
+
```ruby
|
1562
|
+
# Where `options` is a Hash of options provided to Datadog::Tracer
|
1563
|
+
OpenTracing.global_tracer = Datadog::OpenTracer::Tracer.new(options)
|
1564
|
+
```
|
1565
|
+
|
1566
|
+
It can also be configured by using `Datadog.configure` described in the [Tracer settings](#tracer-settings) section.
|
1567
|
+
|
1568
|
+
**Activating and configuring integrations**
|
1569
|
+
|
1570
|
+
By default, configuring OpenTracing with Datadog will not automatically activate any additional instrumentation provided by Datadog. You will only receive spans and traces from OpenTracing instrumentation you have in your application.
|
1571
|
+
|
1572
|
+
However, additional instrumentation provided by Datadog can be activated alongside OpenTracing using `Datadog.configure`, which can be used to further enhance your tracing. To activate this, see [Integration instrumentation](#integration-instrumentation) for more details.
|
1573
|
+
|
1574
|
+
**Supported serialization formats**
|
1575
|
+
|
1576
|
+
| Type | Supported? | Additional information |
|
1577
|
+
| ------------------------------ | ---------- | ---------------------- |
|
1578
|
+
| `OpenTracing::FORMAT_TEXT_MAP` | Yes | |
|
1579
|
+
| `OpenTracing::FORMAT_RACK` | Yes | Because of the loss of resolution in the Rack format, please note that baggage items with names containing either upper case characters or `-` will be converted to lower case and `_` in a round-trip respectively. We recommend avoiding these characters, or accommodating accordingly on the receiving end. |
|
1580
|
+
| `OpenTracing::FORMAT_BINARY` | No | |
|
@@ -39,7 +39,8 @@ module Datadog
|
|
39
39
|
@patched = true
|
40
40
|
end
|
41
41
|
|
42
|
-
if
|
42
|
+
if (!instance_variable_defined?(:@middleware_patched) || !@middleware_patched) \
|
43
|
+
&& get_option(:middleware_names)
|
43
44
|
if get_option(:application)
|
44
45
|
enable_middleware_names
|
45
46
|
@middleware_patched = true
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'ddtrace/contrib/rails/utils'
|
2
|
+
require 'ddtrace/contrib/rails/framework'
|
3
|
+
require 'ddtrace/contrib/rails/middlewares'
|
4
|
+
require 'ddtrace/contrib/rack/middlewares'
|
2
5
|
|
3
6
|
module Datadog
|
4
7
|
module Contrib
|
@@ -17,6 +20,7 @@ module Datadog
|
|
17
20
|
Datadog.configuration[:active_record][:service_name] = value
|
18
21
|
end
|
19
22
|
end
|
23
|
+
option :middleware, default: true
|
20
24
|
option :middleware_names, default: false
|
21
25
|
option :distributed_tracing, default: false
|
22
26
|
option :template_base_path, default: 'views/'
|
@@ -28,7 +32,41 @@ module Datadog
|
|
28
32
|
class << self
|
29
33
|
def patch
|
30
34
|
return @patched if patched? || !compatible?
|
31
|
-
|
35
|
+
|
36
|
+
# Add a callback hook to add the trace middleware before the application initializes.
|
37
|
+
# Otherwise the middleware stack will be frozen.
|
38
|
+
do_once(:rails_before_initialize_hook) do
|
39
|
+
::ActiveSupport.on_load(:before_initialize) do
|
40
|
+
# Sometimes we don't want to activate middleware e.g. OpenTracing, etc.
|
41
|
+
if Datadog.configuration[:rails][:middleware]
|
42
|
+
# Add trace middleware
|
43
|
+
config.middleware.insert_before(0, Datadog::Contrib::Rack::TraceMiddleware)
|
44
|
+
|
45
|
+
# Insert right after Rails exception handling middleware, because if it's before,
|
46
|
+
# it catches and swallows the error. If it's too far after, custom middleware can find itself
|
47
|
+
# between, and raise exceptions that don't end up getting tagged on the request properly.
|
48
|
+
# e.g lost stack trace.
|
49
|
+
config.middleware.insert_after(
|
50
|
+
ActionDispatch::ShowExceptions,
|
51
|
+
Datadog::Contrib::Rails::ExceptionMiddleware
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Add a callback hook to finish configuring the tracer after the application is initialized.
|
58
|
+
# We need to wait for some things, like application name, middleware stack, etc.
|
59
|
+
do_once(:rails_after_initialize_hook) do
|
60
|
+
::ActiveSupport.on_load(:after_initialize) do
|
61
|
+
Datadog::Contrib::Rails::Framework.setup
|
62
|
+
|
63
|
+
# Add instrumentation to Rails components
|
64
|
+
Datadog::Contrib::Rails::ActionController.instrument
|
65
|
+
Datadog::Contrib::Rails::ActionView.instrument
|
66
|
+
Datadog::Contrib::Rails::ActiveSupport.instrument
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
32
70
|
@patched = true
|
33
71
|
rescue => e
|
34
72
|
Datadog::Tracer.log.error("Unable to apply Rails integration: #{e}")
|
@@ -49,5 +87,3 @@ module Datadog
|
|
49
87
|
end
|
50
88
|
end
|
51
89
|
end
|
52
|
-
|
53
|
-
require 'ddtrace/contrib/rails/railtie' if Datadog.registry[:rails].compatible?
|
@@ -5,11 +5,14 @@ require 'ddtrace/contrib/rack/middlewares'
|
|
5
5
|
module Datadog
|
6
6
|
# Railtie class initializes
|
7
7
|
class Railtie < Rails::Railtie
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
# Add the trace middleware to the application stack
|
9
|
+
initializer 'datadog.add_middleware' do |app|
|
10
|
+
app.middleware.insert_before(0, Datadog::Contrib::Rack::TraceMiddleware)
|
11
|
+
# Insert right after Rails exception handling middleware, because if it's before,
|
12
|
+
# it catches and swallows the error. If it's too far after, custom middleware can find itself
|
13
|
+
# between, and raise exceptions that don't end up getting tagged on the request properly (e.g lost stack trace.)
|
14
|
+
app.middleware.insert_after(ActionDispatch::ShowExceptions, Datadog::Contrib::Rails::ExceptionMiddleware)
|
15
|
+
end
|
13
16
|
|
14
17
|
config.after_initialize do
|
15
18
|
Datadog::Contrib::Rails::Framework.setup
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Datadog
|
2
|
+
# Namespace for ddtrace OpenTracing implementation
|
3
|
+
module OpenTracer
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def supported?
|
7
|
+
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.1')
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_opentracer
|
11
|
+
require 'opentracing'
|
12
|
+
require 'opentracing/carrier'
|
13
|
+
require 'ddtrace'
|
14
|
+
require 'ddtrace/opentracer/carrier'
|
15
|
+
require 'ddtrace/opentracer/tracer'
|
16
|
+
require 'ddtrace/opentracer/span'
|
17
|
+
require 'ddtrace/opentracer/span_context'
|
18
|
+
require 'ddtrace/opentracer/span_context_factory'
|
19
|
+
require 'ddtrace/opentracer/scope'
|
20
|
+
require 'ddtrace/opentracer/scope_manager'
|
21
|
+
require 'ddtrace/opentracer/thread_local_scope'
|
22
|
+
require 'ddtrace/opentracer/thread_local_scope_manager'
|
23
|
+
require 'ddtrace/opentracer/distributed_headers'
|
24
|
+
require 'ddtrace/opentracer/propagator'
|
25
|
+
require 'ddtrace/opentracer/text_map_propagator'
|
26
|
+
require 'ddtrace/opentracer/binary_propagator'
|
27
|
+
require 'ddtrace/opentracer/rack_propagator'
|
28
|
+
require 'ddtrace/opentracer/global_tracer'
|
29
|
+
|
30
|
+
# Modify the OpenTracing module functions
|
31
|
+
OpenTracing.module_eval do
|
32
|
+
class << self
|
33
|
+
prepend Datadog::OpenTracer::GlobalTracer
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
load_opentracer if supported?
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# OpenTracing propagator for Datadog::OpenTracer::Tracer
|
4
|
+
module BinaryPropagator
|
5
|
+
extend Propagator
|
6
|
+
|
7
|
+
# Inject a SpanContext into the given carrier
|
8
|
+
#
|
9
|
+
# @param span_context [SpanContext]
|
10
|
+
# @param carrier [Carrier] A carrier object of Binary type
|
11
|
+
def self.inject(span_context, carrier)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Extract a SpanContext in Binary format from the given carrier.
|
16
|
+
#
|
17
|
+
# @param carrier [Carrier] A carrier object of Binary type
|
18
|
+
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found
|
19
|
+
def self.extract(carrier)
|
20
|
+
SpanContext::NOOP_INSTANCE
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'ddtrace/span'
|
2
|
+
require 'ddtrace/ext/distributed'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module OpenTracer
|
6
|
+
# DistributedHeaders provides easy access and validation to headers
|
7
|
+
class DistributedHeaders
|
8
|
+
include Datadog::Ext::DistributedTracing
|
9
|
+
|
10
|
+
def initialize(carrier)
|
11
|
+
@carrier = carrier
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
# Sampling priority is optional.
|
16
|
+
!trace_id.nil? && !parent_id.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
def trace_id
|
20
|
+
id HTTP_HEADER_TRACE_ID
|
21
|
+
end
|
22
|
+
|
23
|
+
def parent_id
|
24
|
+
id HTTP_HEADER_PARENT_ID
|
25
|
+
end
|
26
|
+
|
27
|
+
def sampling_priority
|
28
|
+
hdr = @carrier[HTTP_HEADER_SAMPLING_PRIORITY]
|
29
|
+
# It's important to make a difference between no header,
|
30
|
+
# and a header defined to zero.
|
31
|
+
return unless hdr
|
32
|
+
value = hdr.to_i
|
33
|
+
return if value < 0
|
34
|
+
value
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def id(header)
|
40
|
+
value = @carrier[header].to_i
|
41
|
+
return if value.zero? || value >= Datadog::Span::MAX_ID
|
42
|
+
value < 0 ? value + 0x1_0000_0000_0000_0000 : value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# Patch for OpenTracing module
|
4
|
+
module GlobalTracer
|
5
|
+
def global_tracer=(tracer)
|
6
|
+
super.tap do
|
7
|
+
if tracer.class <= Datadog::OpenTracer::Tracer
|
8
|
+
# Update the Datadog global tracer, too.
|
9
|
+
Datadog.instance_variable_set(:@tracer, tracer.datadog_tracer)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# OpenTracing propagator for Datadog::OpenTracer::Tracer
|
4
|
+
module Propagator
|
5
|
+
# Inject a SpanContext into the given carrier
|
6
|
+
#
|
7
|
+
# @param span_context [SpanContext]
|
8
|
+
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
9
|
+
def inject(span_context, carrier)
|
10
|
+
raise NotImplementedError
|
11
|
+
end
|
12
|
+
|
13
|
+
# Extract a SpanContext in the given format from the given carrier.
|
14
|
+
#
|
15
|
+
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
16
|
+
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found
|
17
|
+
def extract(carrier)
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'ddtrace/propagation/http_propagator'
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module OpenTracer
|
5
|
+
# OpenTracing propagator for Datadog::OpenTracer::Tracer
|
6
|
+
module RackPropagator
|
7
|
+
extend Propagator
|
8
|
+
extend Datadog::Ext::DistributedTracing
|
9
|
+
include Datadog::Ext::DistributedTracing
|
10
|
+
|
11
|
+
BAGGAGE_PREFIX = 'ot-baggage-'.freeze
|
12
|
+
BAGGAGE_PREFIX_FORMATTED = 'HTTP_OT_BAGGAGE_'.freeze
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# Inject a SpanContext into the given carrier
|
16
|
+
#
|
17
|
+
# @param span_context [SpanContext]
|
18
|
+
# @param carrier [Carrier] A carrier object of Rack type
|
19
|
+
def inject(span_context, carrier)
|
20
|
+
# Inject Datadog trace properties
|
21
|
+
Datadog::HTTPPropagator.inject!(span_context.datadog_context, carrier)
|
22
|
+
|
23
|
+
# Inject baggage
|
24
|
+
span_context.baggage.each do |key, value|
|
25
|
+
carrier[BAGGAGE_PREFIX + key] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Extract a SpanContext in Rack format from the given carrier.
|
32
|
+
#
|
33
|
+
# @param carrier [Carrier] A carrier object of Rack type
|
34
|
+
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found
|
35
|
+
def extract(carrier)
|
36
|
+
# First extract & build a Datadog context
|
37
|
+
datadog_context = Datadog::HTTPPropagator.extract(carrier)
|
38
|
+
|
39
|
+
# Then extract any other baggage
|
40
|
+
baggage = {}
|
41
|
+
carrier.each do |key, value|
|
42
|
+
baggage[header_to_baggage(key)] = value if baggage_header?(key)
|
43
|
+
end
|
44
|
+
|
45
|
+
SpanContextFactory.build(datadog_context: datadog_context, baggage: baggage)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def baggage_header?(header)
|
51
|
+
header.to_s.start_with?(BAGGAGE_PREFIX_FORMATTED)
|
52
|
+
end
|
53
|
+
|
54
|
+
def header_to_baggage(key)
|
55
|
+
key[BAGGAGE_PREFIX_FORMATTED.length, key.length].downcase
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# OpenTracing adapter for Datadog::Span
|
4
|
+
class Span < ::OpenTracing::Span
|
5
|
+
attr_reader \
|
6
|
+
:datadog_span
|
7
|
+
|
8
|
+
def initialize(datadog_span:, span_context:)
|
9
|
+
@datadog_span = datadog_span
|
10
|
+
@span_context = span_context
|
11
|
+
end
|
12
|
+
|
13
|
+
# Set the name of the operation
|
14
|
+
#
|
15
|
+
# @param [String] name
|
16
|
+
def operation_name=(name)
|
17
|
+
datadog_span.name = name
|
18
|
+
end
|
19
|
+
|
20
|
+
# Span Context
|
21
|
+
#
|
22
|
+
# @return [SpanContext]
|
23
|
+
def context
|
24
|
+
@span_context
|
25
|
+
end
|
26
|
+
|
27
|
+
# Set a tag value on this span
|
28
|
+
# @param key [String] the key of the tag
|
29
|
+
# @param value [String, Numeric, Boolean] the value of the tag. If it's not
|
30
|
+
# a String, Numeric, or Boolean it will be encoded with to_s
|
31
|
+
def set_tag(key, value)
|
32
|
+
tap { datadog_span.set_tag(key, value) }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set a baggage item on the span
|
36
|
+
# @param key [String] the key of the baggage item
|
37
|
+
# @param value [String] the value of the baggage item
|
38
|
+
def set_baggage_item(key, value)
|
39
|
+
tap do
|
40
|
+
# SpanContext is immutable, so to make changes
|
41
|
+
# build a new span context.
|
42
|
+
@span_context = SpanContextFactory.clone(
|
43
|
+
span_context: context,
|
44
|
+
baggage: { key => value }
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get a baggage item
|
50
|
+
# @param key [String] the key of the baggage item
|
51
|
+
# @return [String] value of the baggage item
|
52
|
+
def get_baggage_item(key)
|
53
|
+
context.baggage[key]
|
54
|
+
end
|
55
|
+
|
56
|
+
# @deprecated Use {#log_kv} instead.
|
57
|
+
# Reason: event is an optional standard log field defined in spec and not required. Also,
|
58
|
+
# method name {#log_kv} is more consistent with other language implementations such as Python and Go.
|
59
|
+
#
|
60
|
+
# Add a log entry to this span
|
61
|
+
# @param event [String] event name for the log
|
62
|
+
# @param timestamp [Time] time of the log
|
63
|
+
# @param fields [Hash] Additional information to log
|
64
|
+
def log(event: nil, timestamp: Time.now, **fields)
|
65
|
+
super # Log deprecation warning
|
66
|
+
|
67
|
+
# If the fields specify an error
|
68
|
+
if fields.key?(:'error.object')
|
69
|
+
datadog_span.set_error(fields[:'error.object'])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Add a log entry to this span
|
74
|
+
# @param timestamp [Time] time of the log
|
75
|
+
# @param fields [Hash] Additional information to log
|
76
|
+
def log_kv(timestamp: Time.now, **fields)
|
77
|
+
# If the fields specify an error
|
78
|
+
if fields.key?(:'error.object')
|
79
|
+
datadog_span.set_error(fields[:'error.object'])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Finish the {Span}
|
84
|
+
# @param end_time [Time] custom end time, if not now
|
85
|
+
def finish(end_time: Time.now)
|
86
|
+
datadog_span.finish(end_time)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# OpenTracing adapter for SpanContext
|
4
|
+
class SpanContext < ::OpenTracing::SpanContext
|
5
|
+
attr_reader \
|
6
|
+
:datadog_context
|
7
|
+
|
8
|
+
def initialize(datadog_context:, baggage: {})
|
9
|
+
@datadog_context = datadog_context
|
10
|
+
@baggage = baggage.freeze
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# Creates new Datadog::OpenTracer::SpanContext
|
4
|
+
module SpanContextFactory
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def build(datadog_context:, baggage: {})
|
8
|
+
SpanContext.new(
|
9
|
+
datadog_context: datadog_context,
|
10
|
+
baggage: baggage.dup
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def clone(span_context:, baggage: {})
|
15
|
+
SpanContext.new(
|
16
|
+
datadog_context: span_context.datadog_context,
|
17
|
+
# Merge baggage from previous SpanContext
|
18
|
+
baggage: span_context.baggage.merge(baggage)
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'ddtrace/ext/distributed'
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module OpenTracer
|
5
|
+
# OpenTracing propagator for Datadog::OpenTracer::Tracer
|
6
|
+
module TextMapPropagator
|
7
|
+
extend Propagator
|
8
|
+
extend Datadog::Ext::DistributedTracing
|
9
|
+
include Datadog::Ext::DistributedTracing
|
10
|
+
|
11
|
+
BAGGAGE_PREFIX = 'ot-baggage-'.freeze
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# Inject a SpanContext into the given carrier
|
15
|
+
#
|
16
|
+
# @param span_context [SpanContext]
|
17
|
+
# @param carrier [Carrier] A carrier object of Rack type
|
18
|
+
def inject(span_context, carrier)
|
19
|
+
# Inject Datadog trace properties
|
20
|
+
span_context.datadog_context.tap do |datadog_context|
|
21
|
+
carrier[HTTP_HEADER_TRACE_ID] = datadog_context.trace_id
|
22
|
+
carrier[HTTP_HEADER_PARENT_ID] = datadog_context.span_id
|
23
|
+
carrier[HTTP_HEADER_SAMPLING_PRIORITY] = datadog_context.sampling_priority
|
24
|
+
end
|
25
|
+
|
26
|
+
# Inject baggage
|
27
|
+
span_context.baggage.each do |key, value|
|
28
|
+
carrier[BAGGAGE_PREFIX + key] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Extract a SpanContext in TextMap format from the given carrier.
|
35
|
+
#
|
36
|
+
# @param carrier [Carrier] A carrier object of TextMap type
|
37
|
+
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found
|
38
|
+
def extract(carrier)
|
39
|
+
# First extract & build a Datadog context
|
40
|
+
headers = DistributedHeaders.new(carrier)
|
41
|
+
|
42
|
+
datadog_context = if headers.valid?
|
43
|
+
Datadog::Context.new(
|
44
|
+
trace_id: headers.trace_id,
|
45
|
+
span_id: headers.parent_id,
|
46
|
+
sampling_priority: headers.sampling_priority
|
47
|
+
)
|
48
|
+
else
|
49
|
+
Datadog::Context.new
|
50
|
+
end
|
51
|
+
|
52
|
+
# Then extract any other baggage
|
53
|
+
baggage = {}
|
54
|
+
carrier.each do |key, value|
|
55
|
+
baggage[item_to_baggage(key)] = value if baggage_item?(key)
|
56
|
+
end
|
57
|
+
|
58
|
+
SpanContextFactory.build(datadog_context: datadog_context, baggage: baggage)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def baggage_item?(item)
|
64
|
+
item.to_s.start_with?(BAGGAGE_PREFIX)
|
65
|
+
end
|
66
|
+
|
67
|
+
def item_to_baggage(key)
|
68
|
+
key[BAGGAGE_PREFIX.length, key.length]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# OpenTracing adapter for thread local scopes
|
4
|
+
class ThreadLocalScope < Scope
|
5
|
+
attr_reader \
|
6
|
+
:finish_on_close
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
manager:,
|
10
|
+
span:,
|
11
|
+
finish_on_close: true
|
12
|
+
)
|
13
|
+
super(manager: manager, span: span)
|
14
|
+
@finish_on_close = finish_on_close
|
15
|
+
@previous_scope = manager.active
|
16
|
+
end
|
17
|
+
|
18
|
+
# Mark the end of the active period for the current thread and Scope,
|
19
|
+
# updating the ScopeManager#active in the process.
|
20
|
+
#
|
21
|
+
# NOTE: Calling close more than once on a single Scope instance leads to
|
22
|
+
# undefined behavior.
|
23
|
+
def close
|
24
|
+
return unless equal?(manager.active)
|
25
|
+
span.finish if finish_on_close
|
26
|
+
manager.send(:set_scope, @previous_scope)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Datadog
|
2
|
+
module OpenTracer
|
3
|
+
# OpenTracing adapter for thread local scope management
|
4
|
+
class ThreadLocalScopeManager < ScopeManager
|
5
|
+
# Make a span instance active.
|
6
|
+
#
|
7
|
+
# @param span [Span] the Span that should become active
|
8
|
+
# @param finish_on_close [Boolean] whether the Span should automatically be
|
9
|
+
# finished when Scope#close is called
|
10
|
+
# @return [Scope] instance to control the end of the active period for the
|
11
|
+
# Span. It is a programming error to neglect to call Scope#close on the
|
12
|
+
# returned instance.
|
13
|
+
def activate(span, finish_on_close: true)
|
14
|
+
ThreadLocalScope.new(
|
15
|
+
manager: self,
|
16
|
+
span: span,
|
17
|
+
finish_on_close: finish_on_close
|
18
|
+
).tap do |scope|
|
19
|
+
set_scope(scope)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Scope] the currently active Scope which can be used to access the
|
24
|
+
# currently active Span.
|
25
|
+
#
|
26
|
+
# If there is a non-null Scope, its wrapped Span becomes an implicit parent
|
27
|
+
# (as Reference#CHILD_OF) of any newly-created Span at Tracer#start_active_span
|
28
|
+
# or Tracer#start_span time.
|
29
|
+
def active
|
30
|
+
Thread.current[object_id.to_s]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def set_scope(scope)
|
36
|
+
Thread.current[object_id.to_s] = scope
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'ddtrace/tracer'
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module OpenTracer
|
5
|
+
# OpenTracing adapter for Datadog::Tracer
|
6
|
+
class Tracer < ::OpenTracing::Tracer
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_reader \
|
10
|
+
:datadog_tracer
|
11
|
+
|
12
|
+
def_delegators \
|
13
|
+
:datadog_tracer,
|
14
|
+
:configure
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
super()
|
18
|
+
@datadog_tracer = Datadog::Tracer.new(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [ScopeManager] the current ScopeManager.
|
22
|
+
def scope_manager
|
23
|
+
@scope_manager ||= ThreadLocalScopeManager.new
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns a newly started and activated Scope.
|
27
|
+
#
|
28
|
+
# If the Tracer's ScopeManager#active is not nil, no explicit references
|
29
|
+
# are provided, and `ignore_active_scope` is false, then an inferred
|
30
|
+
# References#CHILD_OF reference is created to the ScopeManager#active's
|
31
|
+
# SpanContext when start_active is invoked.
|
32
|
+
#
|
33
|
+
# @param operation_name [String] The operation name for the Span
|
34
|
+
# @param child_of [SpanContext, Span] SpanContext that acts as a parent to
|
35
|
+
# the newly-started Span. If a Span instance is provided, its
|
36
|
+
# context is automatically substituted. See [Reference] for more
|
37
|
+
# information.
|
38
|
+
#
|
39
|
+
# If specified, the `references` parameter must be omitted.
|
40
|
+
# @param references [Array<Reference>] An array of reference
|
41
|
+
# objects that identify one or more parent SpanContexts.
|
42
|
+
# @param start_time [Time] When the Span started, if not now
|
43
|
+
# @param tags [Hash] Tags to assign to the Span at start time
|
44
|
+
# @param ignore_active_scope [Boolean] whether to create an implicit
|
45
|
+
# References#CHILD_OF reference to the ScopeManager#active.
|
46
|
+
# @param finish_on_close [Boolean] whether span should automatically be
|
47
|
+
# finished when Scope#close is called
|
48
|
+
# @yield [Scope] If an optional block is passed to start_active it will
|
49
|
+
# yield the newly-started Scope. If `finish_on_close` is true then the
|
50
|
+
# Span will be finished automatically after the block is executed.
|
51
|
+
# @return [Scope] The newly-started and activated Scope
|
52
|
+
def start_active_span(operation_name,
|
53
|
+
child_of: nil,
|
54
|
+
references: nil,
|
55
|
+
start_time: Time.now,
|
56
|
+
tags: nil,
|
57
|
+
ignore_active_scope: false,
|
58
|
+
finish_on_close: true)
|
59
|
+
|
60
|
+
# When meant to automatically determine the parent,
|
61
|
+
# Use the active scope first, otherwise fall back to any
|
62
|
+
# context generated by Datadog, so as to append to it and gain
|
63
|
+
# the benefit of any out-of-the-box tracing from Datadog preceding
|
64
|
+
# the OpenTracer::Tracer.
|
65
|
+
#
|
66
|
+
# We do this here instead of in #start_span because #start_span generates
|
67
|
+
# spans that are not assigned to a scope, a.k.a not supposed to be used by
|
68
|
+
# subsequent spans implicitly. By using the existing Datadog context, the span
|
69
|
+
# effectively ends up "assigned to a scope", by virtue of being added to the
|
70
|
+
# Context. Hence, it would behave more like an active span, which is why it
|
71
|
+
# should only be here.
|
72
|
+
unless child_of || ignore_active_scope
|
73
|
+
child_of = if scope_manager.active
|
74
|
+
scope_manager.active.span.context
|
75
|
+
else
|
76
|
+
SpanContextFactory.build(datadog_context: datadog_tracer.call_context)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Create the span, and auto-add it to the Datadog context.
|
81
|
+
span = start_span(
|
82
|
+
operation_name,
|
83
|
+
child_of: child_of,
|
84
|
+
references: references,
|
85
|
+
start_time: start_time,
|
86
|
+
tags: tags,
|
87
|
+
ignore_active_scope: ignore_active_scope
|
88
|
+
)
|
89
|
+
|
90
|
+
# Overwrite the tracer context with the OpenTracing managed context.
|
91
|
+
# This is mostly for the benefit of any out-of-the-box tracing from Datadog,
|
92
|
+
# such that spans generated by that tracing will be attached to the OpenTracer
|
93
|
+
# parent span.
|
94
|
+
datadog_tracer.provider.context = span.datadog_span.context
|
95
|
+
|
96
|
+
scope_manager.activate(span, finish_on_close: finish_on_close).tap do |scope|
|
97
|
+
if block_given?
|
98
|
+
begin
|
99
|
+
yield(scope)
|
100
|
+
ensure
|
101
|
+
scope.close
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Like #start_active_span, but the returned Span has not been registered via the
|
108
|
+
# ScopeManager.
|
109
|
+
#
|
110
|
+
# @param operation_name [String] The operation name for the Span
|
111
|
+
# @param child_of [SpanContext, Span] SpanContext that acts as a parent to
|
112
|
+
# the newly-started Span. If a Span instance is provided, its
|
113
|
+
# context is automatically substituted. See [Reference] for more
|
114
|
+
# information.
|
115
|
+
#
|
116
|
+
# If specified, the `references` parameter must be omitted.
|
117
|
+
# @param references [Array<Reference>] An array of reference
|
118
|
+
# objects that identify one or more parent SpanContexts.
|
119
|
+
# @param start_time [Time] When the Span started, if not now
|
120
|
+
# @param tags [Hash] Tags to assign to the Span at start time
|
121
|
+
# @param ignore_active_scope [Boolean] whether to create an implicit
|
122
|
+
# References#CHILD_OF reference to the ScopeManager#active.
|
123
|
+
# @return [Span] the newly-started Span instance, which has not been
|
124
|
+
# automatically registered via the ScopeManager
|
125
|
+
def start_span(operation_name,
|
126
|
+
child_of: nil,
|
127
|
+
references: nil,
|
128
|
+
start_time: Time.now,
|
129
|
+
tags: nil,
|
130
|
+
ignore_active_scope: false)
|
131
|
+
|
132
|
+
# Derive the OpenTracer::SpanContext to inherit from.
|
133
|
+
parent_span_context = inherited_span_context(child_of, ignore_active_scope: ignore_active_scope)
|
134
|
+
|
135
|
+
# Retrieve Datadog::Context from parent SpanContext.
|
136
|
+
datadog_context = parent_span_context.nil? ? nil : parent_span_context.datadog_context
|
137
|
+
|
138
|
+
# Build the new Datadog span
|
139
|
+
datadog_span = datadog_tracer.start_span(
|
140
|
+
operation_name,
|
141
|
+
child_of: datadog_context,
|
142
|
+
start_time: start_time,
|
143
|
+
tags: tags || {}
|
144
|
+
)
|
145
|
+
|
146
|
+
# Build or extend the OpenTracer::SpanContext
|
147
|
+
span_context = if parent_span_context
|
148
|
+
SpanContextFactory.clone(span_context: parent_span_context)
|
149
|
+
else
|
150
|
+
SpanContextFactory.build(datadog_context: datadog_span.context)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Wrap the Datadog span and OpenTracer::Span context in a OpenTracer::Span
|
154
|
+
Span.new(datadog_span: datadog_span, span_context: span_context)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Inject a SpanContext into the given carrier
|
158
|
+
#
|
159
|
+
# @param span_context [SpanContext]
|
160
|
+
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
|
161
|
+
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
162
|
+
def inject(span_context, format, carrier)
|
163
|
+
case format
|
164
|
+
when OpenTracing::FORMAT_TEXT_MAP
|
165
|
+
TextMapPropagator.inject(span_context, carrier)
|
166
|
+
when OpenTracing::FORMAT_BINARY
|
167
|
+
BinaryPropagator.inject(span_context, carrier)
|
168
|
+
when OpenTracing::FORMAT_RACK
|
169
|
+
RackPropagator.inject(span_context, carrier)
|
170
|
+
else
|
171
|
+
warn 'Unknown inject format'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Extract a SpanContext in the given format from the given carrier.
|
176
|
+
#
|
177
|
+
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
|
178
|
+
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
179
|
+
# @return [SpanContext, nil] the extracted SpanContext or nil if none could be found
|
180
|
+
def extract(format, carrier)
|
181
|
+
case format
|
182
|
+
when OpenTracing::FORMAT_TEXT_MAP
|
183
|
+
TextMapPropagator.extract(carrier)
|
184
|
+
when OpenTracing::FORMAT_BINARY
|
185
|
+
BinaryPropagator.extract(carrier)
|
186
|
+
when OpenTracing::FORMAT_RACK
|
187
|
+
RackPropagator.extract(carrier)
|
188
|
+
else
|
189
|
+
warn 'Unknown extract format'
|
190
|
+
nil
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
def inherited_span_context(parent, ignore_active_scope: false)
|
197
|
+
case parent
|
198
|
+
when Span
|
199
|
+
parent.context
|
200
|
+
when SpanContext
|
201
|
+
parent
|
202
|
+
else
|
203
|
+
ignore_active_scope ? nil : scope_manager.active && scope_manager.active.span.context
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
data/lib/ddtrace/version.rb
CHANGED
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.
|
4
|
+
version: 0.16.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: 2018-09-
|
11
|
+
date: 2018-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: opentracing
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.4.1
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -400,6 +414,22 @@ files:
|
|
400
414
|
- lib/ddtrace/ext/sql.rb
|
401
415
|
- lib/ddtrace/logger.rb
|
402
416
|
- lib/ddtrace/monkey.rb
|
417
|
+
- lib/ddtrace/opentracer.rb
|
418
|
+
- lib/ddtrace/opentracer/binary_propagator.rb
|
419
|
+
- lib/ddtrace/opentracer/carrier.rb
|
420
|
+
- lib/ddtrace/opentracer/distributed_headers.rb
|
421
|
+
- lib/ddtrace/opentracer/global_tracer.rb
|
422
|
+
- lib/ddtrace/opentracer/propagator.rb
|
423
|
+
- lib/ddtrace/opentracer/rack_propagator.rb
|
424
|
+
- lib/ddtrace/opentracer/scope.rb
|
425
|
+
- lib/ddtrace/opentracer/scope_manager.rb
|
426
|
+
- lib/ddtrace/opentracer/span.rb
|
427
|
+
- lib/ddtrace/opentracer/span_context.rb
|
428
|
+
- lib/ddtrace/opentracer/span_context_factory.rb
|
429
|
+
- lib/ddtrace/opentracer/text_map_propagator.rb
|
430
|
+
- lib/ddtrace/opentracer/thread_local_scope.rb
|
431
|
+
- lib/ddtrace/opentracer/thread_local_scope_manager.rb
|
432
|
+
- lib/ddtrace/opentracer/tracer.rb
|
403
433
|
- lib/ddtrace/patcher.rb
|
404
434
|
- lib/ddtrace/pin.rb
|
405
435
|
- lib/ddtrace/pipeline.rb
|