ddtrace 0.23.3 → 0.24.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 +12 -0
- data/CONTRIBUTING.md +85 -0
- data/README.md +4 -34
- data/docs/DevelopmentGuide.md +132 -0
- data/docs/GettingStarted.md +4 -0
- data/lib/ddtrace/configuration/settings.rb +29 -0
- data/lib/ddtrace/distributed_tracing/headers/b3.rb +44 -0
- data/lib/ddtrace/distributed_tracing/headers/b3_single.rb +56 -0
- data/lib/ddtrace/distributed_tracing/headers/datadog.rb +42 -0
- data/lib/ddtrace/distributed_tracing/headers/headers.rb +68 -0
- data/lib/ddtrace/distributed_tracing/headers/helpers.rb +45 -0
- data/lib/ddtrace/environment.rb +8 -0
- data/lib/ddtrace/ext/distributed.rb +13 -0
- data/lib/ddtrace/ext/net.rb +2 -0
- data/lib/ddtrace/propagation/http_propagator.rb +52 -13
- data/lib/ddtrace/runtime/socket.rb +14 -0
- data/lib/ddtrace/sync_writer.rb +12 -0
- data/lib/ddtrace/version.rb +2 -2
- data/lib/ddtrace/writer.rb +17 -0
- metadata +10 -3
- data/lib/ddtrace/propagation/distributed_headers.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 634a3b4b1798b771abe9af49ee6ac02c2b64a4bc
|
4
|
+
data.tar.gz: 8854e2a87b04f4aeaf426eb8320ce9f728565dd0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a816feb5c86306091e2bf300dc2219f9a6c60cb08e41643bfba4f8a4a5832623c2677eedf48778d40a4557b31fe53dc456f8793f02035cca7dc2115fae909e5c
|
7
|
+
data.tar.gz: 203406fe03985bfda50aeb2e886251b74672f066cb43765bbd06450ab6c86d5a98493691876f3cfb8fc1ca69a426276ae770851e39b96a122c2060c2c5ad938e
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,18 @@
|
|
4
4
|
|
5
5
|
## [Unreleased (beta)]
|
6
6
|
|
7
|
+
## [0.24.0] - 2019-05-21
|
8
|
+
|
9
|
+
Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.24.0
|
10
|
+
|
11
|
+
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.23.3...v0.24.0
|
12
|
+
|
13
|
+
### Added
|
14
|
+
|
15
|
+
- B3 header support (#753)
|
16
|
+
- Hostname tagging option (#760)
|
17
|
+
- Contribution and development guides (#754)
|
18
|
+
|
7
19
|
## [0.23.3] - 2019-05-16
|
8
20
|
|
9
21
|
Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.23.3
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
Community contributions to the Datadog tracing library for Ruby are welcome! See below for some basic guidelines.
|
4
|
+
|
5
|
+
## Want to request a new feature?
|
6
|
+
|
7
|
+
Many great ideas for new features come from the community, and we'd be happy to consider yours!
|
8
|
+
|
9
|
+
To share your request, you can [open a Github issue](https://github.com/DataDog/dd-trace-rb/issues/new) with the details about what you'd like to see. At a minimum, please provide:
|
10
|
+
|
11
|
+
- The goal of the new feature
|
12
|
+
- A description of how it might be used or behave
|
13
|
+
- Links to any important resources (e.g. Github repos, websites, screenshots, specifications, diagrams)
|
14
|
+
|
15
|
+
Additionally, if you can, include:
|
16
|
+
|
17
|
+
- A description of how it could be accomplished
|
18
|
+
- Code snippets that might demonstrate its use or implementation
|
19
|
+
- Screenshots or mockups that visually demonstrate the feature
|
20
|
+
- Links to similar features that would serve as a good comparison
|
21
|
+
- (Any other details that would be useful for implementing this feature!)
|
22
|
+
|
23
|
+
Feature requests will be reviewed, discussed, and then added to [our Community project](https://github.com/DataDog/dd-trace-rb/projects/2).
|
24
|
+
|
25
|
+
## Found a bug?
|
26
|
+
|
27
|
+
For any urgent matters (such as outages) or issues concerning the Datadog service or UI, contact our support team via https://docs.datadoghq.com/help/ for direct, faster assistance.
|
28
|
+
|
29
|
+
You may submit bug reports concerning the Datadog tracing library for Ruby by [opening a Github issue](https://github.com/DataDog/dd-trace-rb/issues/new). At a minimum, please provide:
|
30
|
+
|
31
|
+
- A description of the problem
|
32
|
+
- Steps to reproduce
|
33
|
+
- Expected behavior
|
34
|
+
- Actual behavior
|
35
|
+
- Errors (with stack traces) or warnings received
|
36
|
+
- Any details you can share about your configuration including:
|
37
|
+
- Ruby version & platform
|
38
|
+
- `ddtrace` version
|
39
|
+
- Versions of any other relevant gems (or a `Gemfile.lock` if available)
|
40
|
+
- Any configuration settings for the trace library (e.g. `initializers/datadog.rb`)
|
41
|
+
|
42
|
+
If at all possible, also provide:
|
43
|
+
|
44
|
+
- Logs (from the tracer/application/agent) or other diagnostics
|
45
|
+
- Screenshots, links, or other visual aids that are publicly accessible
|
46
|
+
- Code sample or test that reproduces the problem
|
47
|
+
- An explanation of what causes the bug and/or how it can be fixed
|
48
|
+
|
49
|
+
Reports that include rich detail are better, and ones with code that reproduce the bug are best. Bug requests are triaged, reviewed, and added to [our Community project](https://github.com/DataDog/dd-trace-rb/projects/2).
|
50
|
+
|
51
|
+
## Have a patch?
|
52
|
+
|
53
|
+
We welcome code contributions to the library, which you can [submit as a pull request](https://github.com/DataDog/dd-trace-rb/pull/new/master). To create a pull request:
|
54
|
+
|
55
|
+
1. **Fork the repository** from https://github.com/DataDog/dd-trace-rb
|
56
|
+
2. **Make any changes** for your patch.
|
57
|
+
3. **Write tests** that demonstrate how the feature works or how the bug is fixed.
|
58
|
+
4. **Update any documentation** such as `docs/GettingStarted.md`, especially for new features.
|
59
|
+
5. **Submit the pull request** from your fork back to https://github.com/DataDog/dd-trace-rb. Bugs should merge back to `master`, and new features should merge back to the latest `dev` branch (e.g. `0.24-dev`).
|
60
|
+
|
61
|
+
The pull request will be run through our CI pipeline, and a project member will review the changes with you. At a minimum, to be accepted and merged, pull requests must:
|
62
|
+
|
63
|
+
- Have a stated goal and detailed description of the changes made
|
64
|
+
- Include thorough test coverage and documentation, where applicable
|
65
|
+
- Pass all tests and code quality checks (linting/coverage/benchmarks) on CI
|
66
|
+
- Receive at least one approval from a project member with push permissions
|
67
|
+
|
68
|
+
We also recommend that you share in your description:
|
69
|
+
|
70
|
+
- Any motivations or intent for the contribution
|
71
|
+
- Links to any issues/pull requests it might be related to
|
72
|
+
- Links to any webpages or other external resources that might be related to the change
|
73
|
+
- Screenshots, code samples, or other visual aids that demonstrate the changes or how they are implemented
|
74
|
+
- Benchmarks if the feature is anticipated to have performance implications
|
75
|
+
- Any limitations, constraints or risks that are important to consider
|
76
|
+
|
77
|
+
Pull requests will be reviewed and added to [our Community project](https://github.com/DataDog/dd-trace-rb/projects/2).
|
78
|
+
|
79
|
+
For more information on common topics such as debugging locally, or how to write new integrations, check out [our development guide](https://github.com/DataDog/dd-trace-rb/docs/DevelopmentGuide.md). If at any point you have a question or need assistance with your pull request, feel free to mention a project member! We're always happy to help contributors with their pull requests.
|
80
|
+
|
81
|
+
## Final word
|
82
|
+
|
83
|
+
Many thanks to all of our contributors, and looking forward to seeing you on Github! :tada:
|
84
|
+
|
85
|
+
- Datadog Ruby APM Team
|
data/README.md
CHANGED
@@ -13,41 +13,11 @@ For installation, configuration, and details about using the API, check out our
|
|
13
13
|
|
14
14
|
For descriptions of terminology used in APM, take a look at the [official documentation][visualization docs].
|
15
15
|
|
16
|
+
For contributing, checkout the [contribution guidelines][contribution docs] and [development guide][development docs].
|
17
|
+
|
16
18
|
[setup docs]: https://docs.datadoghq.com/tracing/setup/ruby/
|
17
19
|
[api docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md
|
18
20
|
[gem docs]: http://gems.datadoghq.com/trace/docs/
|
19
21
|
[visualization docs]: https://docs.datadoghq.com/tracing/visualization/
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
### Testing
|
24
|
-
|
25
|
-
Configure your environment through:
|
26
|
-
|
27
|
-
$ bundle install
|
28
|
-
$ appraisal install
|
29
|
-
|
30
|
-
You can launch tests using the following Rake commands:
|
31
|
-
|
32
|
-
$ rake test:main # tracer tests
|
33
|
-
$ appraisal rails<version>-<database> rake test:rails # tests Rails matrix
|
34
|
-
$ appraisal contrib rake test:redis # tests Redis integration
|
35
|
-
...
|
36
|
-
|
37
|
-
Run ``rake --tasks`` for the list of available Rake tasks.
|
38
|
-
Run ``appraisal list`` for the list of available appraisals.
|
39
|
-
|
40
|
-
The test suite requires many backing services (PostgreSQL, MySQL, Redis, ...) and we're using
|
41
|
-
``docker`` and ``docker-compose`` to start these services in the CI.
|
42
|
-
To launch properly the test matrix, please [install docker][2] and [docker-compose][3] using
|
43
|
-
the instructions provided by your platform. Then launch them through:
|
44
|
-
|
45
|
-
$ docker-compose up -d
|
46
|
-
|
47
|
-
We also enforce the Ruby [community-driven style guide][1] through Rubocop. Simply launch:
|
48
|
-
|
49
|
-
$ rake rubocop
|
50
|
-
|
51
|
-
[1]: https://github.com/bbatsov/ruby-style-guide
|
52
|
-
[2]: https://www.docker.com/products/docker
|
53
|
-
[3]: https://www.docker.com/products/docker-compose
|
22
|
+
[contribution docs]: https://github.com/DataDog/dd-trace-rb/blob/master/CONTRIBUTING.md
|
23
|
+
[development docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/DevelopmentGuide.md
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# Developing
|
2
|
+
|
3
|
+
This guide covers some of the common how-tos and technical reference material for developing changes within the trace library.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [Setting up](#setting-up)
|
8
|
+
- [Testing](#testing)
|
9
|
+
- [Writing tests](#writing-tests)
|
10
|
+
- [Running tests](#running-tests)
|
11
|
+
- [Checking code quality](#checking-code-quality)
|
12
|
+
- [Appendix](#appendix)
|
13
|
+
- [Writing new integrations](#writing-new-integrations)
|
14
|
+
|
15
|
+
## Setting up
|
16
|
+
|
17
|
+
*NOTE: To test locally, you must have `Docker` and `Docker Compose` installed. See the [Docker documentation](https://docs.docker.com/compose/install/) for details.*
|
18
|
+
|
19
|
+
The trace library uses Docker Compose to create a Ruby environment to develop and test within, as well as containers for any dependencies that might be necessary for certain kinds of tests.
|
20
|
+
|
21
|
+
To start a development environment, choose a target Ruby version (e.g. between `1.9` and `2.4`) then run the following:
|
22
|
+
|
23
|
+
```
|
24
|
+
# In the root directory of the project...
|
25
|
+
cd ~/dd-trace-rb
|
26
|
+
|
27
|
+
# Create and start a Ruby 2.3 test environment with its dependencies
|
28
|
+
docker-compose run --rm tracer-2.3 /bin/bash
|
29
|
+
|
30
|
+
# Then inside the container (e.g. `root@2a73c6d8673e:/app`)...
|
31
|
+
# Install the library dependencies
|
32
|
+
bundle install
|
33
|
+
|
34
|
+
# Install build targets
|
35
|
+
appraisal install
|
36
|
+
```
|
37
|
+
|
38
|
+
Then within this container you can [run tests](#running-tests), or [run code quality checks](#checking-code-quality).
|
39
|
+
|
40
|
+
## Testing
|
41
|
+
|
42
|
+
The test suite uses both [Minitest](https://github.com/seattlerb/minitest) and [RSpec](https://rspec.info/) tests to verify the correctness of both the core trace library and its integrations.
|
43
|
+
|
44
|
+
Minitest is deprecated in favor of RSpec; all new tests should be written in RSpec, and only existing minitests should be updated.
|
45
|
+
|
46
|
+
### Writing tests
|
47
|
+
|
48
|
+
New tests should be written as RSpec tests in the `spec/ddtrace` folder. Test files should generally mirror the structure of `lib`.
|
49
|
+
|
50
|
+
All changes should be covered by a corresponding RSpec tests. Unit tests are preferred, and integration tests are accepted where appropriate (e.g. acceptance tests, verifying compatibility with datastores, etc) but should be kept to a minimum.
|
51
|
+
|
52
|
+
**Considerations for CI**
|
53
|
+
|
54
|
+
All tests should run in CI. When adding new `spec.rb` files, you may need to add a test task to ensure your test file is run in CI.
|
55
|
+
|
56
|
+
- Ensure that there is a corresponding Rake task defined in `Rakefile` under the the `spec` namespace, whose pattern matches your test file.
|
57
|
+
- Verify the Rake task is configured to run for the appropriate Ruby runtimes in the `ci` Rake task.
|
58
|
+
|
59
|
+
### Running tests
|
60
|
+
|
61
|
+
Simplest way to run tests is to run `bundle exec rake ci`, which will run the entire test suite, just as CI does.
|
62
|
+
|
63
|
+
**For the core library**
|
64
|
+
|
65
|
+
Run the tests for the core library with:
|
66
|
+
|
67
|
+
```
|
68
|
+
# Run Minitest
|
69
|
+
$ bundle exec rake test:main
|
70
|
+
# Run RSpec
|
71
|
+
$ bundle exec rake spec:main
|
72
|
+
```
|
73
|
+
|
74
|
+
**For integrations**
|
75
|
+
|
76
|
+
Integrations which interact with dependencies not listed in the `ddtrace` gemspec will need to load these dependencies to run their tests.
|
77
|
+
|
78
|
+
To do so, load the dependencies using [Appraisal](https://github.com/thoughtbot/appraisal). You can see a list of available appraisals with `bundle exec appraisal list`, or examine the `Appraisals` file.
|
79
|
+
|
80
|
+
Then to run tests, prefix the test commain with the appraisal. For example:
|
81
|
+
|
82
|
+
```
|
83
|
+
# Runs tests for Rails 3.2 + Postgres
|
84
|
+
$ bundle exec appraisal rails32-postgres spec:rails
|
85
|
+
# Runs tests for Redis
|
86
|
+
$ bundle exec appraisal contrib rake spec:redis
|
87
|
+
```
|
88
|
+
|
89
|
+
**Passing arguments to tests**
|
90
|
+
|
91
|
+
When running RSpec tests, you may pass additional args as parameters to the Rake task. For example:
|
92
|
+
|
93
|
+
```
|
94
|
+
# Runs Redis tests with seed 1234
|
95
|
+
$ bundle exec appraisal contrib rake spec:redis'[--seed,1234]'
|
96
|
+
```
|
97
|
+
|
98
|
+
This can be useful for replicating conditions from CI or isolating certain tests.
|
99
|
+
|
100
|
+
### Checking code quality
|
101
|
+
|
102
|
+
**Linting**
|
103
|
+
|
104
|
+
The trace library uses Rubocop to enforce [code style](https://github.com/bbatsov/ruby-style-guide) and quality. To check, run:
|
105
|
+
|
106
|
+
```
|
107
|
+
$ bundle exec rake rubocop
|
108
|
+
```
|
109
|
+
|
110
|
+
## Appendix
|
111
|
+
|
112
|
+
### Writing new integrations
|
113
|
+
|
114
|
+
Integrations are extensions to the trace library that add support for external dependencies (gems); they typically add auto-instrumentation to popular gems and frameworks. You will find many of our integrations in the `contrib` folder.
|
115
|
+
|
116
|
+
Some general guidelines for adding new integrations:
|
117
|
+
|
118
|
+
- An integration can either be added directly to `dd-trace-rb`, or developed as its own gem that depends on `ddtrace`.
|
119
|
+
- Integrations should implement the configuration API for easy, consistent implementation. (See existing integrations as examples of this.)
|
120
|
+
- All new integrations require documentation, unit/integration tests written in RSpec, and passing CI builds.
|
121
|
+
- It's highly encouraged to share screenshots or other demos of how the new integration looks and works.
|
122
|
+
|
123
|
+
To get started quickly, it's perfectly fine to copy-paste an existing integration to use as a template, then modify it to match your needs. This is usually the fastest, easiest way to bootstrap a new integration and makes the time-to-first-trace often very quick, usually less than an hour if it's a simple implementation.
|
124
|
+
|
125
|
+
Once you have it working in your application, you can [add unit tests](#writing-tests), [run them locally](#running-tests), and [check for code quality](#checking-code-quality) using Docker Compose.
|
126
|
+
|
127
|
+
Then [open a pull request](https://github.com/DataDog/dd-trace-rb/CONTRIBUTING.md#have-a-patch) and be sure to add the following to the description:
|
128
|
+
|
129
|
+
- [Documentation](https://github.com/DataDog/dd-trace-rb/docs/GettingStarted.md) for the integration, including versions supported.
|
130
|
+
- Links to the repository/website of the library being integrated
|
131
|
+
- Screenshots showing a sample trace
|
132
|
+
- Any additional code snippets, sample apps, benchmarks, or other resources that demonstrate its implementation are a huge plus!
|
data/docs/GettingStarted.md
CHANGED
@@ -11,9 +11,13 @@ For details about contributing, check out the [development guide][development do
|
|
11
11
|
|
12
12
|
For descriptions of terminology used in APM, take a look at the [official documentation][visualization docs].
|
13
13
|
|
14
|
+
For contributing, checkout the [contribution guidelines][contribution docs] and [development guide][development docs].
|
15
|
+
|
14
16
|
[setup docs]: https://docs.datadoghq.com/tracing/setup/ruby/
|
15
17
|
[development docs]: https://github.com/DataDog/dd-trace-rb/blob/master/README.md#development
|
16
18
|
[visualization docs]: https://docs.datadoghq.com/tracing/visualization/
|
19
|
+
[contribution docs]: https://github.com/DataDog/dd-trace-rb/blob/master/CONTRIBUTING.md
|
20
|
+
[development docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/DevelopmentGuide.md
|
17
21
|
|
18
22
|
## Table of Contents
|
19
23
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ddtrace/ext/analytics'
|
2
|
+
require 'ddtrace/ext/distributed'
|
2
3
|
require 'ddtrace/ext/runtime'
|
3
4
|
require 'ddtrace/configuration/options'
|
4
5
|
|
@@ -17,10 +18,32 @@ module Datadog
|
|
17
18
|
default: -> { env_to_bool(Ext::Analytics::ENV_TRACE_ANALYTICS_ENABLED, nil) },
|
18
19
|
lazy: true
|
19
20
|
|
21
|
+
option :report_hostname,
|
22
|
+
default: -> { env_to_bool(Ext::NET::ENV_REPORT_HOSTNAME, false) },
|
23
|
+
lazy: true
|
24
|
+
|
20
25
|
option :runtime_metrics_enabled,
|
21
26
|
default: -> { env_to_bool(Ext::Runtime::Metrics::ENV_ENABLED, false) },
|
22
27
|
lazy: true
|
23
28
|
|
29
|
+
# Look for all headers by default
|
30
|
+
option :propagation_extract_style,
|
31
|
+
default: lambda {
|
32
|
+
env_to_list(Ext::DistributedTracing::PROPAGATION_EXTRACT_STYLE_ENV,
|
33
|
+
[Ext::DistributedTracing::PROPAGATION_STYLE_DATADOG,
|
34
|
+
Ext::DistributedTracing::PROPAGATION_STYLE_B3,
|
35
|
+
Ext::DistributedTracing::PROPAGATION_STYLE_B3_SINGLE_HEADER])
|
36
|
+
},
|
37
|
+
lazy: true
|
38
|
+
|
39
|
+
# Only inject Datadog headers by default
|
40
|
+
option :propagation_inject_style,
|
41
|
+
default: lambda {
|
42
|
+
env_to_list(Ext::DistributedTracing::PROPAGATION_INJECT_STYLE_ENV,
|
43
|
+
[Ext::DistributedTracing::PROPAGATION_STYLE_DATADOG])
|
44
|
+
},
|
45
|
+
lazy: true
|
46
|
+
|
24
47
|
option :tracer, default: Tracer.new
|
25
48
|
|
26
49
|
def initialize(options = {})
|
@@ -36,6 +59,12 @@ module Datadog
|
|
36
59
|
yield(self) if block_given?
|
37
60
|
end
|
38
61
|
|
62
|
+
def distributed_tracing
|
63
|
+
# TODO: Move distributed tracing configuration to it's own Settings sub-class
|
64
|
+
# DEV: We do this to fake `Datadog.configuration.distributed_tracing.propagation_inject_style`
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
39
68
|
def runtime_metrics(options = nil)
|
40
69
|
runtime_metrics = get_option(:tracer).writer.runtime_metrics
|
41
70
|
return runtime_metrics if options.nil?
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ddtrace/ext/distributed'
|
2
|
+
require 'ddtrace/distributed_tracing/headers/headers'
|
3
|
+
require 'ddtrace/distributed_tracing/headers/helpers'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module DistributedTracing
|
7
|
+
module Headers
|
8
|
+
# B3 provides helpers to inject or extract headers for B3 style headers
|
9
|
+
module B3
|
10
|
+
include Ext::DistributedTracing
|
11
|
+
|
12
|
+
def self.inject!(context, env)
|
13
|
+
return if context.nil?
|
14
|
+
|
15
|
+
# DEV: We need these to be hex encoded
|
16
|
+
env[B3_HEADER_TRACE_ID] = context.trace_id.to_s(16)
|
17
|
+
env[B3_HEADER_SPAN_ID] = context.span_id.to_s(16)
|
18
|
+
|
19
|
+
unless context.sampling_priority.nil?
|
20
|
+
sampling_priority = DistributedTracing::Headers::Helpers.clamp_sampling_priority(context.sampling_priority)
|
21
|
+
env[B3_HEADER_SAMPLED] = sampling_priority.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.extract(env)
|
26
|
+
# Extract values from headers
|
27
|
+
# DEV: B3 doesn't have "origin"
|
28
|
+
headers = Headers.new(env)
|
29
|
+
trace_id = headers.id(B3_HEADER_TRACE_ID, 16)
|
30
|
+
span_id = headers.id(B3_HEADER_SPAN_ID, 16)
|
31
|
+
# We don't need to try and convert sampled since B3 supports 0/1 (AUTO_REJECT/AUTO_KEEP)
|
32
|
+
sampling_priority = headers.number(B3_HEADER_SAMPLED)
|
33
|
+
|
34
|
+
# Return early if this propagation is not valid
|
35
|
+
return unless trace_id && span_id
|
36
|
+
|
37
|
+
::Datadog::Context.new(trace_id: trace_id,
|
38
|
+
span_id: span_id,
|
39
|
+
sampling_priority: sampling_priority)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ddtrace/ext/distributed'
|
2
|
+
require 'ddtrace/distributed_tracing/headers/headers'
|
3
|
+
require 'ddtrace/distributed_tracing/headers/helpers'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module DistributedTracing
|
7
|
+
module Headers
|
8
|
+
# B3Single provides helpers to inject or extract headers for B3 single header style headers
|
9
|
+
module B3Single
|
10
|
+
include Ext::DistributedTracing
|
11
|
+
|
12
|
+
def self.inject!(context, env)
|
13
|
+
return if context.nil?
|
14
|
+
|
15
|
+
# Header format:
|
16
|
+
# b3: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}
|
17
|
+
# https://github.com/apache/incubator-zipkin-b3-propagation/tree/7c6e9f14d6627832bd80baa87ac7dabee7be23cf#single-header
|
18
|
+
# DEV: `{SamplingState}` and `{ParentSpanId`}` are optional
|
19
|
+
|
20
|
+
# DEV: We need these to be hex encoded
|
21
|
+
header = "#{context.trace_id.to_s(16)}-#{context.span_id.to_s(16)}"
|
22
|
+
|
23
|
+
unless context.sampling_priority.nil?
|
24
|
+
sampling_priority = DistributedTracing::Headers::Helpers.clamp_sampling_priority(context.sampling_priority)
|
25
|
+
header += "-#{sampling_priority}"
|
26
|
+
end
|
27
|
+
|
28
|
+
env[B3_HEADER_SINGLE] = header
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.extract(env)
|
32
|
+
# Header format:
|
33
|
+
# b3: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}
|
34
|
+
# https://github.com/apache/incubator-zipkin-b3-propagation/tree/7c6e9f14d6627832bd80baa87ac7dabee7be23cf#single-header
|
35
|
+
# DEV: `{SamplingState}` and `{ParentSpanId`}` are optional
|
36
|
+
|
37
|
+
headers = Headers.new(env)
|
38
|
+
value = headers.header(B3_HEADER_SINGLE)
|
39
|
+
return if value.nil?
|
40
|
+
|
41
|
+
parts = value.split('-')
|
42
|
+
trace_id = headers.value_to_id(parts[0], 16) unless parts.empty?
|
43
|
+
span_id = headers.value_to_id(parts[1], 16) if parts.length > 1
|
44
|
+
sampling_priority = headers.value_to_number(parts[2]) if parts.length > 2
|
45
|
+
|
46
|
+
# Return early if this propagation is not valid
|
47
|
+
return unless trace_id && span_id
|
48
|
+
|
49
|
+
::Datadog::Context.new(trace_id: trace_id,
|
50
|
+
span_id: span_id,
|
51
|
+
sampling_priority: sampling_priority)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'ddtrace/ext/distributed'
|
2
|
+
require 'ddtrace/distributed_tracing/headers/headers'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module DistributedTracing
|
6
|
+
module Headers
|
7
|
+
# Datadog provides helpers to inject or extract headers for Datadog style headers
|
8
|
+
module Datadog
|
9
|
+
include Ext::DistributedTracing
|
10
|
+
|
11
|
+
def self.inject!(context, env)
|
12
|
+
return if context.nil?
|
13
|
+
|
14
|
+
env[HTTP_HEADER_TRACE_ID] = context.trace_id.to_s
|
15
|
+
env[HTTP_HEADER_PARENT_ID] = context.span_id.to_s
|
16
|
+
env[HTTP_HEADER_SAMPLING_PRIORITY] = context.sampling_priority.to_s unless context.sampling_priority.nil?
|
17
|
+
env[HTTP_HEADER_ORIGIN] = context.origin.to_s unless context.origin.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.extract(env)
|
21
|
+
# Extract values from headers
|
22
|
+
headers = Headers.new(env)
|
23
|
+
trace_id = headers.id(HTTP_HEADER_TRACE_ID)
|
24
|
+
parent_id = headers.id(HTTP_HEADER_PARENT_ID)
|
25
|
+
origin = headers.header(HTTP_HEADER_ORIGIN)
|
26
|
+
sampling_priority = headers.number(HTTP_HEADER_SAMPLING_PRIORITY)
|
27
|
+
|
28
|
+
# Return early if this propagation is not valid
|
29
|
+
# DEV: To be valid we need to have a trace id and a parent id or when it is a synthetics trace, just the trace id
|
30
|
+
# DEV: `DistributedHeaders#id` will not return 0
|
31
|
+
return unless (trace_id && parent_id) || (origin == 'synthetics' && trace_id)
|
32
|
+
|
33
|
+
# Return new context
|
34
|
+
::Datadog::Context.new(trace_id: trace_id,
|
35
|
+
span_id: parent_id,
|
36
|
+
origin: origin,
|
37
|
+
sampling_priority: sampling_priority)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'ddtrace/configuration'
|
2
|
+
require 'ddtrace/span'
|
3
|
+
require 'ddtrace/ext/distributed'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module DistributedTracing
|
7
|
+
module Headers
|
8
|
+
# Headers provides easy access and validation methods for Rack headers
|
9
|
+
class Headers
|
10
|
+
include Ext::DistributedTracing
|
11
|
+
|
12
|
+
def initialize(env)
|
13
|
+
@env = env
|
14
|
+
end
|
15
|
+
|
16
|
+
def header(name)
|
17
|
+
rack_header = "http-#{name}".upcase!.tr('-', '_')
|
18
|
+
|
19
|
+
hdr = @env[rack_header]
|
20
|
+
|
21
|
+
# Only return the value if it is not an empty string
|
22
|
+
hdr if hdr != ''
|
23
|
+
end
|
24
|
+
|
25
|
+
def id(hdr, base = 10)
|
26
|
+
value_to_id(header(hdr), base)
|
27
|
+
end
|
28
|
+
|
29
|
+
def value_to_id(value, base = 10)
|
30
|
+
id = value_to_number(value, base)
|
31
|
+
|
32
|
+
# Return early if we could not parse a number
|
33
|
+
return if id.nil?
|
34
|
+
|
35
|
+
# Zero or greater than max allowed value of 2**64
|
36
|
+
return if id.zero? || id > Span::EXTERNAL_MAX_ID
|
37
|
+
id < 0 ? id + (2**64) : id
|
38
|
+
end
|
39
|
+
|
40
|
+
def number(hdr, base = 10)
|
41
|
+
value_to_number(header(hdr), base)
|
42
|
+
end
|
43
|
+
|
44
|
+
def value_to_number(value, base = 10)
|
45
|
+
# It's important to make a difference between no header,
|
46
|
+
# and a header defined to zero.
|
47
|
+
return if value.nil?
|
48
|
+
|
49
|
+
# Be sure we have a string
|
50
|
+
value = value.to_s
|
51
|
+
|
52
|
+
# If we are parsing base16 number then truncate to 64-bit
|
53
|
+
value = DistributedTracing::Headers::Helpers.truncate_base16_number(value) if base == 16
|
54
|
+
|
55
|
+
# Convert header to an integer
|
56
|
+
# DEV: Ruby `.to_i` will return `0` if a number could not be parsed
|
57
|
+
num = value.to_i(base)
|
58
|
+
|
59
|
+
# Ensure the parsed number is the same as the original string value
|
60
|
+
# e.g. We want to make sure to throw away `'nan'.to_i == 0`
|
61
|
+
return unless num.to_s(base) == value
|
62
|
+
|
63
|
+
num
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'ddtrace/configuration'
|
2
|
+
require 'ddtrace/span'
|
3
|
+
require 'ddtrace/ext/priority'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module DistributedTracing
|
7
|
+
module Headers
|
8
|
+
# Helpers module provides common helper functions for distributed tracing headers
|
9
|
+
module Helpers
|
10
|
+
# Base provides common methods for distributed header helper classes
|
11
|
+
def self.clamp_sampling_priority(sampling_priority)
|
12
|
+
# B3 doesn't have our -1 (USER_REJECT) and 2 (USER_KEEP) priorities so convert to acceptable 0/1
|
13
|
+
if sampling_priority < 0
|
14
|
+
sampling_priority = Ext::Priority::AUTO_REJECT
|
15
|
+
elsif sampling_priority > 1
|
16
|
+
sampling_priority = Ext::Priority::AUTO_KEEP
|
17
|
+
end
|
18
|
+
|
19
|
+
sampling_priority
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.truncate_base16_number(value)
|
23
|
+
# Lowercase if we want to parse base16 e.g. 3E8 => 3e8
|
24
|
+
# DEV: Ruby will parse `3E8` just fine, but to test
|
25
|
+
# `num.to_s(base) == value` we need to lowercase
|
26
|
+
value = value.downcase
|
27
|
+
|
28
|
+
# Truncate to trailing 16 characters if length is greater than 16
|
29
|
+
# https://github.com/apache/incubator-zipkin/blob/21fe362899fef5c593370466bc5707d3837070c2/zipkin/src/main/java/zipkin2/storage/StorageComponent.java#L49-L53
|
30
|
+
# DEV: This ensures we truncate B3 128-bit trace and span ids to 64-bit
|
31
|
+
value = value[value.length - 16, 16] if value.length > 16
|
32
|
+
|
33
|
+
# Remove any leading zeros
|
34
|
+
# DEV: When we call `num.to_s(16)` later Ruby will not add leading zeros
|
35
|
+
# for us so we want to make sure the comparision will work as expected
|
36
|
+
# DEV: regex, remove all leading zeros up until we find the last 0 in the string
|
37
|
+
# or we find the first non-zero, this allows `'0000' -> '0'` and `'00001' -> '1'`
|
38
|
+
value = value.sub(/^0*(?=(0$)|[^0])/, '')
|
39
|
+
|
40
|
+
value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/ddtrace/environment.rb
CHANGED
@@ -10,6 +10,14 @@ module Datadog
|
|
10
10
|
def env_to_float(var, default = nil)
|
11
11
|
ENV.key?(var) ? ENV[var].to_f : default
|
12
12
|
end
|
13
|
+
|
14
|
+
def env_to_list(var, default = [])
|
15
|
+
if ENV.key?(var)
|
16
|
+
ENV[var].split(',').map(&:strip)
|
17
|
+
else
|
18
|
+
default
|
19
|
+
end
|
20
|
+
end
|
13
21
|
end
|
14
22
|
end
|
15
23
|
end
|
@@ -10,6 +10,19 @@ module Datadog
|
|
10
10
|
HTTP_HEADER_ORIGIN = 'x-datadog-origin'.freeze
|
11
11
|
ORIGIN_KEY = '_dd.origin'.freeze
|
12
12
|
|
13
|
+
# B3 headers used for distributed tracing
|
14
|
+
B3_HEADER_TRACE_ID = 'x-b3-traceid'.freeze
|
15
|
+
B3_HEADER_SPAN_ID = 'x-b3-spanid'.freeze
|
16
|
+
B3_HEADER_SAMPLED = 'x-b3-sampled'.freeze
|
17
|
+
B3_HEADER_SINGLE = 'b3'.freeze
|
18
|
+
|
19
|
+
# Distributed tracing propagation options
|
20
|
+
PROPAGATION_STYLE_DATADOG = 'Datadog'.freeze
|
21
|
+
PROPAGATION_STYLE_B3 = 'B3'.freeze
|
22
|
+
PROPAGATION_STYLE_B3_SINGLE_HEADER = 'B3 single header'.freeze
|
23
|
+
PROPAGATION_INJECT_STYLE_ENV = 'DD_PROPAGATION_INJECT_STYLE'.freeze
|
24
|
+
PROPAGATION_EXTRACT_STYLE_ENV = 'DD_PROPAGATION_EXTRACT_STYLE'.freeze
|
25
|
+
|
13
26
|
# gRPC metadata keys for distributed tracing. https://github.com/grpc/grpc-go/blob/v1.10.x/Documentation/grpc-metadata.md
|
14
27
|
GRPC_METADATA_TRACE_ID = 'x-datadog-trace-id'.freeze
|
15
28
|
GRPC_METADATA_PARENT_ID = 'x-datadog-parent-id'.freeze
|
data/lib/ddtrace/ext/net.rb
CHANGED
@@ -1,36 +1,75 @@
|
|
1
|
+
require 'ddtrace/configuration'
|
1
2
|
require 'ddtrace/context'
|
2
3
|
require 'ddtrace/ext/distributed'
|
3
|
-
require 'ddtrace/
|
4
|
+
require 'ddtrace/ext/priority'
|
5
|
+
require 'ddtrace/distributed_tracing/headers/b3'
|
6
|
+
require 'ddtrace/distributed_tracing/headers/b3_single'
|
7
|
+
require 'ddtrace/distributed_tracing/headers/datadog'
|
4
8
|
|
5
9
|
module Datadog
|
6
10
|
# HTTPPropagator helps extracting and injecting HTTP headers.
|
7
11
|
module HTTPPropagator
|
8
12
|
include Ext::DistributedTracing
|
9
13
|
|
14
|
+
PROPAGATION_STYLES = { PROPAGATION_STYLE_B3 => DistributedTracing::Headers::B3,
|
15
|
+
PROPAGATION_STYLE_B3_SINGLE_HEADER => DistributedTracing::Headers::B3Single,
|
16
|
+
PROPAGATION_STYLE_DATADOG => DistributedTracing::Headers::Datadog }.freeze
|
17
|
+
|
10
18
|
# inject! popolates the env with span ID, trace ID and sampling priority
|
11
19
|
def self.inject!(context, env)
|
12
20
|
# Prevent propagation from being attempted if context provided is nil.
|
13
21
|
if context.nil?
|
14
|
-
Datadog::Tracer.log.debug('Cannot inject context into env to propagate over HTTP: context is nil.'.freeze)
|
22
|
+
::Datadog::Tracer.log.debug('Cannot inject context into env to propagate over HTTP: context is nil.'.freeze)
|
15
23
|
return
|
16
24
|
end
|
17
25
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
# Inject all configured propagation styles
|
27
|
+
::Datadog.configuration.propagation_inject_style.each do |style|
|
28
|
+
propagator = PROPAGATION_STYLES[style]
|
29
|
+
propagator.inject!(context, env) unless propagator.nil?
|
30
|
+
end
|
23
31
|
end
|
24
32
|
|
25
33
|
# extract returns a context containing the span ID, trace ID and
|
26
34
|
# sampling priority defined in env.
|
27
35
|
def self.extract(env)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
context = nil
|
37
|
+
dd_context = nil
|
38
|
+
|
39
|
+
::Datadog.configuration.propagation_extract_style.each do |style|
|
40
|
+
propagator = PROPAGATION_STYLES[style]
|
41
|
+
next if propagator.nil?
|
42
|
+
|
43
|
+
# Extract context
|
44
|
+
# DEV: `propagator.extract` will return `nil`, where `HTTPPropagator#extract` will not
|
45
|
+
extracted_context = propagator.extract(env)
|
46
|
+
# Skip this style if no valid headers were found
|
47
|
+
next if extracted_context.nil?
|
48
|
+
|
49
|
+
# Keep track of the Datadog extract context, we want to return
|
50
|
+
# this one if we have one
|
51
|
+
dd_context = extracted_context if extracted_context && style == PROPAGATION_STYLE_DATADOG
|
52
|
+
|
53
|
+
# No previously extracted context, use the one we just extracted
|
54
|
+
if context.nil?
|
55
|
+
context = extracted_context
|
56
|
+
else
|
57
|
+
unless context.trace_id == extracted_context.trace_id && context.span_id == extracted_context.span_id
|
58
|
+
# Return an empty/new context if we have a mismatch in values extracted
|
59
|
+
msg = "#{context.trace_id} != #{extracted_context.trace_id} && " \
|
60
|
+
"#{context.span_id} != #{extracted_context.span_id}"
|
61
|
+
::Datadog::Tracer.log.debug("Cannot extract context from HTTP: extracted contexts differ, #{msg}".freeze)
|
62
|
+
# DEV: This will return from `self.extract` not this `each` block
|
63
|
+
return ::Datadog::Context.new
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Return the extracted context if we found one or else a new empty context
|
69
|
+
# Always return the Datadog context if one exists since it has more
|
70
|
+
# information than the B3 headers e.g. origin, expanded priority
|
71
|
+
# sampling values, etc
|
72
|
+
dd_context || context || ::Datadog::Context.new
|
34
73
|
end
|
35
74
|
end
|
36
75
|
end
|
data/lib/ddtrace/sync_writer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ddtrace/ext/net'
|
2
|
+
require 'ddtrace/runtime/socket'
|
1
3
|
require 'ddtrace/runtime/metrics'
|
2
4
|
|
3
5
|
module Datadog
|
@@ -44,7 +46,17 @@ module Datadog
|
|
44
46
|
|
45
47
|
def flush_trace(trace)
|
46
48
|
processed_traces = Pipeline.process!([trace])
|
49
|
+
inject_hostname!(processed_traces.first) if Datadog.configuration.report_hostname
|
47
50
|
transport.send(:traces, processed_traces)
|
48
51
|
end
|
52
|
+
|
53
|
+
def inject_hostname!(trace)
|
54
|
+
unless trace.first.nil?
|
55
|
+
hostname = Datadog::Runtime::Socket.hostname
|
56
|
+
unless hostname.nil? || hostname.empty?
|
57
|
+
trace.first.set_tag(Ext::NET::TAG_HOSTNAME, hostname)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
49
61
|
end
|
50
62
|
end
|
data/lib/ddtrace/version.rb
CHANGED
data/lib/ddtrace/writer.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'ddtrace/ext/net'
|
2
|
+
require 'ddtrace/runtime/socket'
|
3
|
+
|
1
4
|
require 'ddtrace/transport'
|
2
5
|
require 'ddtrace/encoding'
|
3
6
|
require 'ddtrace/workers'
|
@@ -70,6 +73,9 @@ module Datadog
|
|
70
73
|
def send_spans(traces, transport)
|
71
74
|
return true if traces.empty?
|
72
75
|
|
76
|
+
# Inject hostname if configured to do so
|
77
|
+
inject_hostname!(traces) if Datadog.configuration.report_hostname
|
78
|
+
|
73
79
|
code = transport.send(:traces, traces)
|
74
80
|
status = !transport.server_error?(code)
|
75
81
|
@traces_flushed += traces.length if status
|
@@ -126,6 +132,17 @@ module Datadog
|
|
126
132
|
|
127
133
|
private
|
128
134
|
|
135
|
+
def inject_hostname!(traces)
|
136
|
+
traces.each do |trace|
|
137
|
+
next if trace.first.nil?
|
138
|
+
|
139
|
+
hostname = Datadog::Runtime::Socket.hostname
|
140
|
+
unless hostname.nil? || hostname.empty?
|
141
|
+
trace.first.set_tag(Ext::NET::TAG_HOSTNAME, hostname)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
129
146
|
def sampling_updater(action, response, api)
|
130
147
|
return unless action == :traces && response.is_a?(Net::HTTPOK)
|
131
148
|
|
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.24.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-05-
|
11
|
+
date: 2019-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -301,6 +301,7 @@ files:
|
|
301
301
|
- ".yardopts"
|
302
302
|
- Appraisals
|
303
303
|
- CHANGELOG.md
|
304
|
+
- CONTRIBUTING.md
|
304
305
|
- Gemfile
|
305
306
|
- LICENSE
|
306
307
|
- README.md
|
@@ -309,6 +310,7 @@ files:
|
|
309
310
|
- benchmarks/sidekiq_test.rb
|
310
311
|
- ddtrace.gemspec
|
311
312
|
- docker-compose.yml
|
313
|
+
- docs/DevelopmentGuide.md
|
312
314
|
- docs/GettingStarted.md
|
313
315
|
- lib/ddtrace.rb
|
314
316
|
- lib/ddtrace/analytics.rb
|
@@ -516,6 +518,11 @@ files:
|
|
516
518
|
- lib/ddtrace/contrib/sucker_punch/integration.rb
|
517
519
|
- lib/ddtrace/contrib/sucker_punch/patcher.rb
|
518
520
|
- lib/ddtrace/correlation.rb
|
521
|
+
- lib/ddtrace/distributed_tracing/headers/b3.rb
|
522
|
+
- lib/ddtrace/distributed_tracing/headers/b3_single.rb
|
523
|
+
- lib/ddtrace/distributed_tracing/headers/datadog.rb
|
524
|
+
- lib/ddtrace/distributed_tracing/headers/headers.rb
|
525
|
+
- lib/ddtrace/distributed_tracing/headers/helpers.rb
|
519
526
|
- lib/ddtrace/encoding.rb
|
520
527
|
- lib/ddtrace/environment.rb
|
521
528
|
- lib/ddtrace/error.rb
|
@@ -555,7 +562,6 @@ files:
|
|
555
562
|
- lib/ddtrace/pipeline.rb
|
556
563
|
- lib/ddtrace/pipeline/span_filter.rb
|
557
564
|
- lib/ddtrace/pipeline/span_processor.rb
|
558
|
-
- lib/ddtrace/propagation/distributed_headers.rb
|
559
565
|
- lib/ddtrace/propagation/grpc_propagator.rb
|
560
566
|
- lib/ddtrace/propagation/http_propagator.rb
|
561
567
|
- lib/ddtrace/provider.rb
|
@@ -565,6 +571,7 @@ files:
|
|
565
571
|
- lib/ddtrace/runtime/gc.rb
|
566
572
|
- lib/ddtrace/runtime/identity.rb
|
567
573
|
- lib/ddtrace/runtime/metrics.rb
|
574
|
+
- lib/ddtrace/runtime/socket.rb
|
568
575
|
- lib/ddtrace/runtime/thread_count.rb
|
569
576
|
- lib/ddtrace/sampler.rb
|
570
577
|
- lib/ddtrace/span.rb
|
@@ -1,70 +0,0 @@
|
|
1
|
-
require 'ddtrace/span'
|
2
|
-
require 'ddtrace/ext/distributed'
|
3
|
-
|
4
|
-
module Datadog
|
5
|
-
# DistributedHeaders provides easy access and validation to headers
|
6
|
-
class DistributedHeaders
|
7
|
-
include Ext::DistributedTracing
|
8
|
-
|
9
|
-
def initialize(env)
|
10
|
-
@env = env
|
11
|
-
end
|
12
|
-
|
13
|
-
def valid?
|
14
|
-
# Synthetics sends us `X-Datadog-Parent-Id: 0` which normally we would want
|
15
|
-
# to filter out, but is ok in this context since there is no parent from Synthetics
|
16
|
-
return true if origin == 'synthetics' && trace_id
|
17
|
-
|
18
|
-
# Sampling priority and origin are optional.
|
19
|
-
# DEV: We want to explicitly return true/false here
|
20
|
-
trace_id && parent_id ? true : false
|
21
|
-
end
|
22
|
-
|
23
|
-
def trace_id
|
24
|
-
id HTTP_HEADER_TRACE_ID
|
25
|
-
end
|
26
|
-
|
27
|
-
def parent_id
|
28
|
-
id HTTP_HEADER_PARENT_ID
|
29
|
-
end
|
30
|
-
|
31
|
-
def sampling_priority
|
32
|
-
hdr = header(HTTP_HEADER_SAMPLING_PRIORITY)
|
33
|
-
|
34
|
-
# It's important to make a difference between no header,
|
35
|
-
# and a header defined to zero.
|
36
|
-
return if hdr.nil?
|
37
|
-
|
38
|
-
# Convert header to an integer
|
39
|
-
value = hdr.to_i
|
40
|
-
|
41
|
-
# Ensure the parsed number is the same as the original string value
|
42
|
-
# e.g. We want to make sure to throw away `'nan'.to_i == 0`
|
43
|
-
# DEV: Ruby `.to_i` will return `0` if a number could not be parsed
|
44
|
-
return unless value.to_s == hdr.to_s
|
45
|
-
|
46
|
-
value
|
47
|
-
end
|
48
|
-
|
49
|
-
def origin
|
50
|
-
hdr = header(HTTP_HEADER_ORIGIN)
|
51
|
-
# Only return the value if it is not an empty string
|
52
|
-
hdr if hdr != ''
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def header(name)
|
58
|
-
rack_header = "http-#{name}".upcase!.tr('-', '_')
|
59
|
-
|
60
|
-
@env[rack_header]
|
61
|
-
end
|
62
|
-
|
63
|
-
def id(header)
|
64
|
-
value = header(header).to_i
|
65
|
-
# Zero or greater than max allowed value of 2**64
|
66
|
-
return if value.zero? || value > Span::EXTERNAL_MAX_ID
|
67
|
-
value < 0 ? value + 0x1_0000_0000_0000_0000 : value
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|