ddtrace 0.41.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Appraisals +55 -5
- data/CHANGELOG.md +31 -1
- data/CONTRIBUTING.md +1 -1
- data/Rakefile +20 -0
- data/ddtrace.gemspec +1 -0
- data/docs/DevelopmentGuide.md +10 -0
- data/docs/GettingStarted.md +5 -2
- data/lib/ddtrace/buffer.rb +229 -133
- data/lib/ddtrace/context_provider.rb +6 -5
- data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +1 -0
- data/lib/ddtrace/contrib/delayed_job/ext.rb +2 -0
- data/lib/ddtrace/contrib/delayed_job/plugin.rb +37 -15
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +1 -1
- data/lib/ddtrace/contrib/rails/patcher.rb +15 -4
- data/lib/ddtrace/contrib/resque/integration.rb +1 -1
- data/lib/ddtrace/propagation/grpc_propagator.rb +16 -4
- data/lib/ddtrace/tracer.rb +8 -8
- data/lib/ddtrace/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 356d9acad651e21531cb323e2894fd187a02e91bd1c68973bf8030b2aa1512a3
|
|
4
|
+
data.tar.gz: e9997b324030189490fc43e67dc3a9e4ba4ec9c334e9fe7a08c14ea66b25145b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e276f69c9c8c39c63c6b5c8abc7572d18d635f549f0a152acd2fbbd9a3cfe4cb151112fb2a928f0785c054a416087d97fd6650ce057b199598123f89df43e57
|
|
7
|
+
data.tar.gz: edc8ad3cd84b445c276f8d26f76ab9d404ce234154ea916fac94c65122628ce2b6cd6f74df450af19e231fe1d20a7f21ed8ee8707c70a7647f58fee51ee16912
|
data/Appraisals
CHANGED
|
@@ -539,6 +539,16 @@ elsif Gem::Version.new('2.3.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
539
539
|
gem 'lograge'
|
|
540
540
|
end
|
|
541
541
|
|
|
542
|
+
appraise 'resque2-redis3' do
|
|
543
|
+
gem 'redis', '< 4.0'
|
|
544
|
+
gem 'resque', '>= 2.0'
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
appraise 'resque2-redis4' do
|
|
548
|
+
gem 'redis', '>= 4.0'
|
|
549
|
+
gem 'resque', '>= 2.0'
|
|
550
|
+
end
|
|
551
|
+
|
|
542
552
|
appraise 'contrib' do
|
|
543
553
|
gem 'actionpack'
|
|
544
554
|
gem 'actionview'
|
|
@@ -569,7 +579,7 @@ elsif Gem::Version.new('2.3.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
569
579
|
gem 'rake', '>= 12.3'
|
|
570
580
|
gem 'redis', '< 4.0'
|
|
571
581
|
gem 'rest-client'
|
|
572
|
-
gem 'resque'
|
|
582
|
+
gem 'resque'
|
|
573
583
|
gem 'ruby-kafka', '>= 0.7.10'
|
|
574
584
|
gem 'sequel'
|
|
575
585
|
gem 'shoryuken'
|
|
@@ -628,6 +638,16 @@ elsif Gem::Version.new('2.4.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
628
638
|
gem 'lograge'
|
|
629
639
|
end
|
|
630
640
|
|
|
641
|
+
appraise 'resque2-redis3' do
|
|
642
|
+
gem 'redis', '< 4.0'
|
|
643
|
+
gem 'resque', '>= 2.0'
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
appraise 'resque2-redis4' do
|
|
647
|
+
gem 'redis', '>= 4.0'
|
|
648
|
+
gem 'resque', '>= 2.0'
|
|
649
|
+
end
|
|
650
|
+
|
|
631
651
|
appraise 'contrib' do
|
|
632
652
|
gem 'actionpack'
|
|
633
653
|
gem 'actionview'
|
|
@@ -658,7 +678,7 @@ elsif Gem::Version.new('2.4.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
658
678
|
gem 'rake', '>= 12.3'
|
|
659
679
|
gem 'redis', '< 4.0'
|
|
660
680
|
gem 'rest-client'
|
|
661
|
-
gem 'resque'
|
|
681
|
+
gem 'resque'
|
|
662
682
|
gem 'ruby-kafka', '>= 0.7.10'
|
|
663
683
|
gem 'sequel'
|
|
664
684
|
gem 'shoryuken'
|
|
@@ -765,6 +785,16 @@ elsif Gem::Version.new('2.5.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
765
785
|
gem 'lograge'
|
|
766
786
|
end
|
|
767
787
|
|
|
788
|
+
appraise 'resque2-redis3' do
|
|
789
|
+
gem 'redis', '< 4.0'
|
|
790
|
+
gem 'resque', '>= 2.0'
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
appraise 'resque2-redis4' do
|
|
794
|
+
gem 'redis', '>= 4.0'
|
|
795
|
+
gem 'resque', '>= 2.0'
|
|
796
|
+
end
|
|
797
|
+
|
|
768
798
|
appraise 'contrib' do
|
|
769
799
|
gem 'actionpack'
|
|
770
800
|
gem 'actionview'
|
|
@@ -796,7 +826,7 @@ elsif Gem::Version.new('2.5.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
796
826
|
gem 'rake', '>= 12.3'
|
|
797
827
|
gem 'redis', '< 4.0'
|
|
798
828
|
gem 'rest-client'
|
|
799
|
-
gem 'resque'
|
|
829
|
+
gem 'resque'
|
|
800
830
|
gem 'ruby-kafka', '>= 0.7.10'
|
|
801
831
|
gem 'sequel'
|
|
802
832
|
gem 'shoryuken'
|
|
@@ -893,6 +923,16 @@ elsif Gem::Version.new('2.6.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
893
923
|
gem 'lograge'
|
|
894
924
|
end
|
|
895
925
|
|
|
926
|
+
appraise 'resque2-redis3' do
|
|
927
|
+
gem 'redis', '< 4.0'
|
|
928
|
+
gem 'resque', '>= 2.0'
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
appraise 'resque2-redis4' do
|
|
932
|
+
gem 'redis', '>= 4.0'
|
|
933
|
+
gem 'resque', '>= 2.0'
|
|
934
|
+
end
|
|
935
|
+
|
|
896
936
|
appraise 'contrib' do
|
|
897
937
|
gem 'actionpack'
|
|
898
938
|
gem 'actionview'
|
|
@@ -922,7 +962,7 @@ elsif Gem::Version.new('2.6.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
|
922
962
|
gem 'rake', '>= 12.3'
|
|
923
963
|
gem 'redis', '< 4.0'
|
|
924
964
|
gem 'rest-client'
|
|
925
|
-
gem 'resque'
|
|
965
|
+
gem 'resque'
|
|
926
966
|
gem 'ruby-kafka', '>= 0.7.10'
|
|
927
967
|
gem 'sequel'
|
|
928
968
|
gem 'shoryuken'
|
|
@@ -1023,6 +1063,16 @@ elsif Gem::Version.new('2.7.0') <= Gem::Version.new(RUBY_VERSION)
|
|
|
1023
1063
|
gem 'lograge'
|
|
1024
1064
|
end
|
|
1025
1065
|
|
|
1066
|
+
appraise 'resque2-redis3' do
|
|
1067
|
+
gem 'redis', '< 4.0'
|
|
1068
|
+
gem 'resque', '>= 2.0'
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1071
|
+
appraise 'resque2-redis4' do
|
|
1072
|
+
gem 'redis', '>= 4.0'
|
|
1073
|
+
gem 'resque', '>= 2.0'
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1026
1076
|
appraise 'contrib' do
|
|
1027
1077
|
gem 'actionpack'
|
|
1028
1078
|
gem 'actionview'
|
|
@@ -1051,7 +1101,7 @@ elsif Gem::Version.new('2.7.0') <= Gem::Version.new(RUBY_VERSION)
|
|
|
1051
1101
|
gem 'rake', '>= 12.3'
|
|
1052
1102
|
gem 'redis', '< 4.0'
|
|
1053
1103
|
gem 'rest-client'
|
|
1054
|
-
gem 'resque'
|
|
1104
|
+
gem 'resque'
|
|
1055
1105
|
gem 'ruby-kafka', '>= 0.7.10'
|
|
1056
1106
|
gem 'sequel'
|
|
1057
1107
|
gem 'shoryuken'
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.42.0] - 2020-10-21
|
|
6
|
+
|
|
7
|
+
Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.42.0
|
|
8
|
+
|
|
9
|
+
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.41.0...v0.42.0
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Increase Resque support to include 2.0 (#1213) (@erict-square)
|
|
14
|
+
|
|
15
|
+
- Improve gRPC Propagator to support metadata array values (#1203) (@mdehoog)
|
|
16
|
+
|
|
17
|
+
- Add CPU benchmarks, diagnostics to tests (#1188, #1198)
|
|
18
|
+
|
|
19
|
+
- Access active correlation by Thread (#1200)
|
|
20
|
+
|
|
21
|
+
- Improve delayed_job instrumentation (#1187) (@norbertnytko)
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Improve Rails `log_injection` option to support more Lograge formats (#1210) (@Supy)
|
|
28
|
+
|
|
29
|
+
- Fix Changelog (#1199) (@y-yagi)
|
|
30
|
+
|
|
31
|
+
### Refactored
|
|
32
|
+
|
|
33
|
+
- Refactor Trace buffer into multiple components (#1195)
|
|
34
|
+
|
|
5
35
|
## [0.41.0] - 2020-09-30
|
|
6
36
|
|
|
7
37
|
Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.41.0
|
|
@@ -17,7 +47,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.40.0...v0.41.0
|
|
|
17
47
|
- Add peer.service tag to external services and skip tagging external services with language tag for runtime metrics (#934, #935, #1180)
|
|
18
48
|
- This helps support the way runtime metrics are associated with spans in the UI.
|
|
19
49
|
- Faster TraceBuffer for CRuby (#1172)
|
|
20
|
-
- Reduce memory usage during gem
|
|
50
|
+
- Reduce memory usage during gem startup (#1090)
|
|
21
51
|
- Reduce memory usage of the HTTP transport (#1165)
|
|
22
52
|
|
|
23
53
|
### Fixed
|
data/CONTRIBUTING.md
CHANGED
|
@@ -56,7 +56,7 @@ We welcome code contributions to the library, which you can [submit as a pull re
|
|
|
56
56
|
2. **Make any changes** for your patch.
|
|
57
57
|
3. **Write tests** that demonstrate how the feature works or how the bug is fixed.
|
|
58
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
|
|
59
|
+
5. **Submit the pull request** from your fork back to the latest revision of the `master` branch on https://github.com/DataDog/dd-trace-rb.
|
|
60
60
|
|
|
61
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
62
|
|
data/Rakefile
CHANGED
|
@@ -464,6 +464,10 @@ task :ci do
|
|
|
464
464
|
declare 'bundle exec appraisal rails4-postgres rake spec:rails'
|
|
465
465
|
declare 'bundle exec appraisal rails5-mysql2 rake spec:rails'
|
|
466
466
|
declare 'bundle exec appraisal rails5-postgres rake spec:rails'
|
|
467
|
+
|
|
468
|
+
# explicitly test resque-2x compatability
|
|
469
|
+
declare 'bundle exec appraisal resque2-redis3 rake spec:resque'
|
|
470
|
+
declare 'bundle exec appraisal resque2-redis4 rake spec:resque'
|
|
467
471
|
end
|
|
468
472
|
elsif Gem::Version.new('2.4.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
469
473
|
&& Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
|
|
@@ -525,6 +529,10 @@ task :ci do
|
|
|
525
529
|
# Rails specs
|
|
526
530
|
declare 'bundle exec appraisal rails5-mysql2 rake spec:rails'
|
|
527
531
|
declare 'bundle exec appraisal rails5-postgres rake spec:rails'
|
|
532
|
+
|
|
533
|
+
# explicitly test resque-2x compatability
|
|
534
|
+
declare 'bundle exec appraisal resque2-redis3 rake spec:resque'
|
|
535
|
+
declare 'bundle exec appraisal resque2-redis4 rake spec:resque'
|
|
528
536
|
end
|
|
529
537
|
elsif Gem::Version.new('2.5.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
530
538
|
&& Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
|
|
@@ -594,6 +602,10 @@ task :ci do
|
|
|
594
602
|
# declare 'bundle exec appraisal rails6-mysql2 rake spec:action_cable' # TODO: Hangs CI jobs... fix and re-enable.
|
|
595
603
|
declare 'bundle exec appraisal rails6-mysql2 rake spec:rails'
|
|
596
604
|
declare 'bundle exec appraisal rails6-postgres rake spec:rails'
|
|
605
|
+
|
|
606
|
+
# explicitly test resque-2x compatability
|
|
607
|
+
declare 'bundle exec appraisal resque2-redis3 rake spec:resque'
|
|
608
|
+
declare 'bundle exec appraisal resque2-redis4 rake spec:resque'
|
|
597
609
|
elsif Gem::Version.new('2.6.0') <= Gem::Version.new(RUBY_VERSION) \
|
|
598
610
|
&& Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
|
|
599
611
|
# Main library
|
|
@@ -664,6 +676,10 @@ task :ci do
|
|
|
664
676
|
# declare 'bundle exec appraisal rails6-mysql2 rake spec:action_cable' # TODO: Hangs CI jobs... fix and re-enable.
|
|
665
677
|
declare 'bundle exec appraisal rails6-mysql2 rake spec:rails'
|
|
666
678
|
declare 'bundle exec appraisal rails6-postgres rake spec:rails'
|
|
679
|
+
|
|
680
|
+
# explicitly test resque-2x compatability
|
|
681
|
+
declare 'bundle exec appraisal resque2-redis3 rake spec:resque'
|
|
682
|
+
declare 'bundle exec appraisal resque2-redis4 rake spec:resque'
|
|
667
683
|
end
|
|
668
684
|
elsif Gem::Version.new('2.7.0') <= Gem::Version.new(RUBY_VERSION)
|
|
669
685
|
# Main library
|
|
@@ -732,6 +748,10 @@ task :ci do
|
|
|
732
748
|
declare 'bundle exec appraisal rails5-postgres rake spec:rails'
|
|
733
749
|
declare 'bundle exec appraisal rails6-mysql2 rake spec:rails'
|
|
734
750
|
declare 'bundle exec appraisal rails6-postgres rake spec:rails'
|
|
751
|
+
|
|
752
|
+
# explicitly test resque-2x compatability
|
|
753
|
+
declare 'bundle exec appraisal resque2-redis3 rake spec:resque'
|
|
754
|
+
declare 'bundle exec appraisal resque2-redis4 rake spec:resque'
|
|
735
755
|
end
|
|
736
756
|
end
|
|
737
757
|
end
|
data/ddtrace.gemspec
CHANGED
|
@@ -46,6 +46,7 @@ Gem::Specification.new do |spec|
|
|
|
46
46
|
spec.add_development_dependency 'rubocop', '= 0.49.1' if RUBY_VERSION >= '2.1.0'
|
|
47
47
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
48
48
|
spec.add_development_dependency 'rspec-collection_matchers', '~> 1.1'
|
|
49
|
+
spec.add_development_dependency 'ruby-prof', '~> 1.4' if RUBY_PLATFORM != 'java' && RUBY_VERSION >= '2.4.0'
|
|
49
50
|
spec.add_development_dependency 'minitest', '= 5.10.1'
|
|
50
51
|
spec.add_development_dependency 'minitest-around', '0.5.0'
|
|
51
52
|
spec.add_development_dependency 'minitest-stub_any_instance', '1.0.2'
|
data/docs/DevelopmentGuide.md
CHANGED
|
@@ -124,6 +124,16 @@ The trace library uses Rubocop to enforce [code style](https://github.com/bbatso
|
|
|
124
124
|
$ bundle exec rake rubocop
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
### Running benchmarks
|
|
128
|
+
|
|
129
|
+
If your changes can have a measurable performance impact, we recommend running our benchmark suite:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
$ bundle exec rake spec:benchmark
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Results are printed to STDOUT as well as written to the `./tmp/benchmark/` directory.
|
|
136
|
+
|
|
127
137
|
## Appendix
|
|
128
138
|
|
|
129
139
|
### Writing new integrations
|
data/docs/GettingStarted.md
CHANGED
|
@@ -359,7 +359,7 @@ For a list of available integrations, and their configuration options, please re
|
|
|
359
359
|
| Rails | `rails` | `>= 3.0` | `>= 3.0` | *[Link](#rails)* | *[Link](https://github.com/rails/rails)* |
|
|
360
360
|
| Rake | `rake` | `>= 12.0` | `>= 12.0` | *[Link](#rake)* | *[Link](https://github.com/ruby/rake)* |
|
|
361
361
|
| Redis | `redis` | `>= 3.2` | `>= 3.2` | *[Link](#redis)* | *[Link](https://github.com/redis/redis-rb)* |
|
|
362
|
-
| Resque | `resque` | `>= 1.0
|
|
362
|
+
| Resque | `resque` | `>= 1.0` | `>= 1.0` | *[Link](#resque)* | *[Link](https://github.com/resque/resque)* |
|
|
363
363
|
| Rest Client | `rest-client` | `>= 1.8` | `>= 1.8` | *[Link](#rest-client)* | *[Link](https://github.com/rest-client/rest-client)* |
|
|
364
364
|
| Sequel | `sequel` | `>= 3.41` | `>= 3.41` | *[Link](#sequel)* | *[Link](https://github.com/jeremyevans/sequel)* |
|
|
365
365
|
| Shoryuken | `shoryuken` | `>= 3.2` | `>= 3.2` | *[Link](#shoryuken)* | *[Link](https://github.com/phstc/shoryuken)* |
|
|
@@ -617,7 +617,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
|
|
|
617
617
|
|
|
618
618
|
### DelayedJob
|
|
619
619
|
|
|
620
|
-
The DelayedJob integration uses lifecycle hooks to trace the job executions.
|
|
620
|
+
The DelayedJob integration uses lifecycle hooks to trace the job executions and enqueues.
|
|
621
621
|
|
|
622
622
|
You can enable it through `Datadog.configure`:
|
|
623
623
|
|
|
@@ -635,6 +635,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
|
|
|
635
635
|
| --- | ----------- | ------- |
|
|
636
636
|
| `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
|
|
637
637
|
| `service_name` | Service name used for `DelayedJob` instrumentation | `'delayed_job'` |
|
|
638
|
+
| `client_service_name` | Service name used for client-side `DelayedJob` instrumentation | `'delayed_job-client'` |
|
|
638
639
|
|
|
639
640
|
### Elasticsearch
|
|
640
641
|
|
|
@@ -2045,6 +2046,8 @@ Datadog.configure do |c|
|
|
|
2045
2046
|
end
|
|
2046
2047
|
```
|
|
2047
2048
|
|
|
2049
|
+
_Note:_ For `lograge` users who have also defined `lograge.custom_options` in an `initializers/lograge.rb` configuration file, due to the order that Rails loads initializers (alphabetical), automatic trace correlation may not take effect, since `initializers/datadog.rb` would be overwritten by the `initializers/lograge.rb` initializer. To support automatic trace correlation with _existing_ `lograge.custom_options`, use the [Manual (Lograge)](#manual-lograge) configuration below.
|
|
2050
|
+
|
|
2048
2051
|
##### Manual (Lograge)
|
|
2049
2052
|
|
|
2050
2053
|
After [setting up Lograge in a Rails application](https://docs.datadoghq.com/logs/log_collection/ruby/), manually modify the `custom_options` block in your environment configuration file (e.g. `config/environments/production.rb`) to add the trace IDs.
|
data/lib/ddtrace/buffer.rb
CHANGED
|
@@ -5,132 +5,175 @@ require 'ddtrace/runtime/object_space'
|
|
|
5
5
|
# Trace buffer that accumulates traces for a consumer.
|
|
6
6
|
# Consumption can happen from a different thread.
|
|
7
7
|
module Datadog
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@
|
|
15
|
-
@buffer_accepted_lengths = 0
|
|
16
|
-
@buffer_dropped = 0
|
|
17
|
-
@buffer_spans = 0
|
|
8
|
+
# Buffer that stores objects. The buffer has a maximum size and when
|
|
9
|
+
# the buffer is full, a random object is discarded.
|
|
10
|
+
class Buffer
|
|
11
|
+
def initialize(max_size)
|
|
12
|
+
@max_size = max_size
|
|
13
|
+
@items = []
|
|
14
|
+
@closed = false
|
|
18
15
|
end
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
# Add a new ``item`` in the local queue. This method doesn't block the execution
|
|
18
|
+
# even if the buffer is full. In that case, a random item is discarded.
|
|
19
|
+
def push(item)
|
|
20
|
+
return if closed?
|
|
21
|
+
full? ? replace!(item) : add!(item)
|
|
22
|
+
item
|
|
23
|
+
end
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
# A bulk push alternative to +#push+. Use this method if
|
|
26
|
+
# pushing more than one item for efficiency.
|
|
27
|
+
def concat(items)
|
|
28
|
+
return if closed?
|
|
29
|
+
|
|
30
|
+
# Segment items into underflow and overflow
|
|
31
|
+
underflow, overflow = overflow_segments(items)
|
|
32
|
+
|
|
33
|
+
# Concatenate items do not exceed capacity.
|
|
34
|
+
add_all!(underflow) unless underflow.nil?
|
|
35
|
+
|
|
36
|
+
# Iteratively replace items, to ensure pseudo-random replacement.
|
|
37
|
+
overflow.each { |item| replace!(item) } unless overflow.nil?
|
|
27
38
|
end
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
# Stored items are returned and the local buffer is reset.
|
|
41
|
+
def pop
|
|
42
|
+
drain!
|
|
43
|
+
end
|
|
31
44
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
# Return the current number of stored traces.
|
|
46
|
+
def length
|
|
47
|
+
@items.length
|
|
35
48
|
end
|
|
36
49
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
# Return if the buffer is empty.
|
|
51
|
+
def empty?
|
|
52
|
+
@items.empty?
|
|
53
|
+
end
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
# Closes this buffer, preventing further pushing.
|
|
56
|
+
# Draining is still allowed.
|
|
57
|
+
def close
|
|
58
|
+
@closed = true
|
|
59
|
+
end
|
|
45
60
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Datadog.health_metrics.queue_length(traces.length)
|
|
61
|
+
def closed?
|
|
62
|
+
@closed
|
|
63
|
+
end
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
protected
|
|
66
|
+
|
|
67
|
+
# Segment items into two distinct segments: underflow and overflow.
|
|
68
|
+
# Underflow are items that will fit into buffer.
|
|
69
|
+
# Overflow are items that will exceed capacity, after underflow is added.
|
|
70
|
+
# Returns each array, and nil if there is no underflow/overflow.
|
|
71
|
+
def overflow_segments(items)
|
|
72
|
+
underflow = nil
|
|
73
|
+
overflow = nil
|
|
74
|
+
|
|
75
|
+
overflow_size = @max_size > 0 ? (@items.length + items.length) - @max_size : 0
|
|
76
|
+
|
|
77
|
+
if overflow_size > 0
|
|
78
|
+
# Items will overflow
|
|
79
|
+
if overflow_size < items.length
|
|
80
|
+
# Partial overflow
|
|
81
|
+
underflow_end_index = items.length - overflow_size - 1
|
|
82
|
+
underflow = items[0..underflow_end_index]
|
|
83
|
+
overflow = items[(underflow_end_index + 1)..-1]
|
|
84
|
+
else
|
|
85
|
+
# Total overflow
|
|
86
|
+
overflow = items
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
# Items do not exceed capacity.
|
|
90
|
+
underflow = items
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
[underflow, overflow]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def full?
|
|
97
|
+
@max_size > 0 && @items.length >= @max_size
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def add_all!(items)
|
|
101
|
+
@items.concat(items)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def add!(item)
|
|
105
|
+
@items << item
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def replace!(item)
|
|
109
|
+
# Choose random item to be replaced
|
|
110
|
+
replace_index = rand(@items.length)
|
|
111
|
+
|
|
112
|
+
# Replace random item
|
|
113
|
+
discarded_item = @items[replace_index]
|
|
114
|
+
@items[replace_index] = item
|
|
115
|
+
|
|
116
|
+
# Return discarded item
|
|
117
|
+
discarded_item
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def drain!
|
|
121
|
+
items = @items
|
|
122
|
+
@items = []
|
|
123
|
+
items
|
|
58
124
|
end
|
|
59
125
|
end
|
|
60
126
|
|
|
61
|
-
#
|
|
127
|
+
# Buffer that stores objects, has a maximum size, and
|
|
62
128
|
# can be safely used concurrently on any environment.
|
|
63
129
|
#
|
|
64
130
|
# This implementation uses a {Mutex} around public methods, incurring
|
|
65
|
-
# overhead in order to ensure
|
|
131
|
+
# overhead in order to ensure thread-safety.
|
|
66
132
|
#
|
|
67
133
|
# This is implementation is recommended for non-CRuby environments.
|
|
68
|
-
# If using CRuby, {Datadog::
|
|
69
|
-
class ThreadSafeBuffer <
|
|
134
|
+
# If using CRuby, {Datadog::CRubyBuffer} is a faster implementation with minimal compromise.
|
|
135
|
+
class ThreadSafeBuffer < Buffer
|
|
70
136
|
def initialize(max_size)
|
|
71
|
-
super
|
|
72
|
-
|
|
73
|
-
@max_size = max_size
|
|
137
|
+
super
|
|
74
138
|
|
|
75
|
-
@mutex = Mutex.new
|
|
76
|
-
@traces = []
|
|
77
|
-
@closed = false
|
|
139
|
+
@mutex = Mutex.new
|
|
78
140
|
end
|
|
79
141
|
|
|
80
|
-
# Add a new ``
|
|
81
|
-
# even if the buffer is full. In that case, a random
|
|
82
|
-
def push(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
len = @traces.length
|
|
86
|
-
if len < @max_size || @max_size <= 0
|
|
87
|
-
@traces << trace
|
|
88
|
-
else
|
|
89
|
-
# we should replace a random trace with the new one
|
|
90
|
-
replace_index = rand(len)
|
|
91
|
-
replaced_trace = @traces[replace_index]
|
|
92
|
-
@traces[replace_index] = trace
|
|
93
|
-
measure_drop(replaced_trace)
|
|
94
|
-
end
|
|
142
|
+
# Add a new ``item`` in the local queue. This method doesn't block the execution
|
|
143
|
+
# even if the buffer is full. In that case, a random item is discarded.
|
|
144
|
+
def push(item)
|
|
145
|
+
synchronize { super }
|
|
146
|
+
end
|
|
95
147
|
|
|
96
|
-
|
|
97
|
-
|
|
148
|
+
def concat(items)
|
|
149
|
+
synchronize { super }
|
|
98
150
|
end
|
|
99
151
|
|
|
100
152
|
# Return the current number of stored traces.
|
|
101
153
|
def length
|
|
102
|
-
|
|
103
|
-
return @traces.length
|
|
104
|
-
end
|
|
154
|
+
synchronize { super }
|
|
105
155
|
end
|
|
106
156
|
|
|
107
157
|
# Return if the buffer is empty.
|
|
108
158
|
def empty?
|
|
109
|
-
|
|
110
|
-
return @traces.empty?
|
|
111
|
-
end
|
|
159
|
+
synchronize { super }
|
|
112
160
|
end
|
|
113
161
|
|
|
114
162
|
# Stored traces are returned and the local buffer is reset.
|
|
115
163
|
def pop
|
|
116
|
-
|
|
117
|
-
traces = @traces
|
|
118
|
-
@traces = []
|
|
119
|
-
|
|
120
|
-
measure_pop(traces)
|
|
121
|
-
|
|
122
|
-
return traces
|
|
123
|
-
end
|
|
164
|
+
synchronize { super }
|
|
124
165
|
end
|
|
125
166
|
|
|
126
167
|
def close
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
168
|
+
synchronize { super }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def synchronize
|
|
172
|
+
@mutex.synchronize { yield }
|
|
130
173
|
end
|
|
131
174
|
end
|
|
132
175
|
|
|
133
|
-
#
|
|
176
|
+
# Buffer that stores objects, has a maximum size, and
|
|
134
177
|
# can be safely used concurrently with CRuby.
|
|
135
178
|
#
|
|
136
179
|
# Under extreme concurrency scenarios, this class can exceed
|
|
@@ -151,80 +194,133 @@ module Datadog
|
|
|
151
194
|
#
|
|
152
195
|
# @see spec/ddtrace/benchmark/buffer_benchmark_spec.rb Buffer benchmarks
|
|
153
196
|
# @see https://github.com/ruby-concurrency/concurrent-ruby/blob/c1114a0c6891d9634f019f1f9fe58dcae8658964/lib/concurrent-ruby/concurrent/array.rb#L23-L27
|
|
154
|
-
class
|
|
155
|
-
|
|
156
|
-
|
|
197
|
+
class CRubyBuffer < Buffer
|
|
198
|
+
# Add a new ``trace`` in the local queue. This method doesn't block the execution
|
|
199
|
+
# even if the buffer is full. In that case, a random trace is discarded.
|
|
200
|
+
def replace!(item)
|
|
201
|
+
# we should replace a random trace with the new one
|
|
202
|
+
replace_index = rand(@items.size)
|
|
203
|
+
replaced_trace = @items.delete_at(replace_index)
|
|
204
|
+
@items << item
|
|
205
|
+
|
|
206
|
+
# We might have deleted an element right when the buffer
|
|
207
|
+
# was drained, thus +replaced_trace+ will be +nil+.
|
|
208
|
+
# In that case, nothing was replaced, and this method
|
|
209
|
+
# performed a simple insertion into the buffer.
|
|
210
|
+
replaced_trace
|
|
211
|
+
end
|
|
212
|
+
end
|
|
157
213
|
|
|
158
|
-
|
|
214
|
+
# Health metrics for trace buffers.
|
|
215
|
+
module MeasuredBuffer
|
|
216
|
+
def initialize(*_)
|
|
217
|
+
super
|
|
159
218
|
|
|
160
|
-
@
|
|
161
|
-
@
|
|
219
|
+
@buffer_accepted = 0
|
|
220
|
+
@buffer_accepted_lengths = 0
|
|
221
|
+
@buffer_dropped = 0
|
|
222
|
+
@buffer_spans = 0
|
|
162
223
|
end
|
|
163
224
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def push(trace)
|
|
167
|
-
return if @closed
|
|
168
|
-
len = @traces.length
|
|
169
|
-
if len < @max_size || @max_size <= 0
|
|
170
|
-
@traces << trace
|
|
171
|
-
else
|
|
172
|
-
# we should replace a random trace with the new one
|
|
173
|
-
replace_index = rand(len)
|
|
174
|
-
replaced_trace = @traces.delete_at(replace_index)
|
|
175
|
-
@traces << trace
|
|
176
|
-
|
|
177
|
-
# Check if we deleted the element right when the buffer
|
|
178
|
-
# was popped. In that case we didn't actually delete anything,
|
|
179
|
-
# we just inserted into a newly cleared buffer instead.
|
|
180
|
-
measure_drop(replaced_trace) if replaced_trace
|
|
181
|
-
end
|
|
225
|
+
def add!(trace)
|
|
226
|
+
super
|
|
182
227
|
|
|
228
|
+
# Emit health metrics
|
|
183
229
|
measure_accept(trace)
|
|
184
230
|
end
|
|
185
231
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
@traces.length
|
|
189
|
-
end
|
|
232
|
+
def add_all!(traces)
|
|
233
|
+
super
|
|
190
234
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
@traces.empty?
|
|
235
|
+
# Emit health metrics
|
|
236
|
+
traces.each { |trace| measure_accept(trace) }
|
|
194
237
|
end
|
|
195
238
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
traces = @traces.pop(VERY_LARGE_INTEGER)
|
|
239
|
+
def replace!(trace)
|
|
240
|
+
discarded_trace = super
|
|
199
241
|
|
|
200
|
-
|
|
242
|
+
# Emit health metrics
|
|
243
|
+
measure_accept(trace)
|
|
244
|
+
measure_drop(discarded_trace) if discarded_trace
|
|
245
|
+
|
|
246
|
+
discarded_trace
|
|
247
|
+
end
|
|
201
248
|
|
|
249
|
+
# Stored traces are returned and the local buffer is reset.
|
|
250
|
+
def drain!
|
|
251
|
+
traces = super
|
|
252
|
+
measure_pop(traces)
|
|
202
253
|
traces
|
|
203
254
|
end
|
|
204
255
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
256
|
+
def measure_accept(trace)
|
|
257
|
+
@buffer_accepted += 1
|
|
258
|
+
@buffer_accepted_lengths += trace.length
|
|
208
259
|
|
|
209
|
-
|
|
210
|
-
|
|
260
|
+
@buffer_spans += trace.length
|
|
261
|
+
rescue StandardError => e
|
|
262
|
+
Datadog.logger.debug("Failed to measure queue accept. Cause: #{e.message} Source: #{e.backtrace.first}")
|
|
211
263
|
end
|
|
264
|
+
|
|
265
|
+
def measure_drop(trace)
|
|
266
|
+
@buffer_dropped += 1
|
|
267
|
+
|
|
268
|
+
@buffer_spans -= trace.length
|
|
269
|
+
rescue StandardError => e
|
|
270
|
+
Datadog.logger.debug("Failed to measure queue drop. Cause: #{e.message} Source: #{e.backtrace.first}")
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def measure_pop(traces)
|
|
274
|
+
# Accepted, cumulative totals
|
|
275
|
+
Datadog.health_metrics.queue_accepted(@buffer_accepted)
|
|
276
|
+
Datadog.health_metrics.queue_accepted_lengths(@buffer_accepted_lengths)
|
|
277
|
+
|
|
278
|
+
# Dropped, cumulative totals
|
|
279
|
+
Datadog.health_metrics.queue_dropped(@buffer_dropped)
|
|
280
|
+
# TODO: are we missing a +queue_dropped_lengths+ metric?
|
|
281
|
+
|
|
282
|
+
# Queue gauges, current values
|
|
283
|
+
Datadog.health_metrics.queue_max_length(@max_size)
|
|
284
|
+
Datadog.health_metrics.queue_spans(@buffer_spans)
|
|
285
|
+
Datadog.health_metrics.queue_length(traces.length)
|
|
286
|
+
|
|
287
|
+
# Reset aggregated metrics
|
|
288
|
+
@buffer_accepted = 0
|
|
289
|
+
@buffer_accepted_lengths = 0
|
|
290
|
+
@buffer_dropped = 0
|
|
291
|
+
@buffer_spans = 0
|
|
292
|
+
rescue StandardError => e
|
|
293
|
+
Datadog.logger.debug("Failed to measure queue. Cause: #{e.message} Source: #{e.backtrace.first}")
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Trace buffer that stores application traces, has a maximum size, and
|
|
298
|
+
# can be safely used concurrently on any environment.
|
|
299
|
+
#
|
|
300
|
+
# @see {Datadog::ThreadSafeBuffer}
|
|
301
|
+
class ThreadSafeTraceBuffer < ThreadSafeBuffer
|
|
302
|
+
prepend MeasuredBuffer
|
|
212
303
|
end
|
|
213
304
|
|
|
214
|
-
#
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
305
|
+
# Trace buffer that stores application traces, has a maximum size, and
|
|
306
|
+
# can be safely used concurrently with CRuby.
|
|
307
|
+
#
|
|
308
|
+
# @see {Datadog::CRubyBuffer}
|
|
309
|
+
class CRubyTraceBuffer < CRubyBuffer
|
|
310
|
+
prepend MeasuredBuffer
|
|
311
|
+
end
|
|
221
312
|
|
|
222
313
|
# Trace buffer that stores application traces. The buffer has a maximum size and when
|
|
223
314
|
# the buffer is full, a random trace is discarded. This class is thread-safe and is used
|
|
224
315
|
# automatically by the ``Tracer`` instance when a ``Span`` is finished.
|
|
225
316
|
#
|
|
317
|
+
# We choose the default TraceBuffer implementation for current platform dynamically here.
|
|
318
|
+
#
|
|
226
319
|
# TODO We should restructure this module, so that classes are not declared at top-level ::Datadog.
|
|
227
320
|
# TODO Making such a change is potentially breaking for users manually configuring the tracer.
|
|
228
|
-
|
|
229
|
-
|
|
321
|
+
TraceBuffer = if Datadog::Ext::Runtime::RUBY_ENGINE == 'ruby' # rubocop:disable Style/ConstantName
|
|
322
|
+
CRubyTraceBuffer
|
|
323
|
+
else
|
|
324
|
+
ThreadSafeTraceBuffer
|
|
325
|
+
end
|
|
230
326
|
end
|
|
@@ -13,9 +13,9 @@ module Datadog
|
|
|
13
13
|
@context.local = ctx
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
# Return the
|
|
17
|
-
def context
|
|
18
|
-
@context.local
|
|
16
|
+
# Return the local context.
|
|
17
|
+
def context(key = nil)
|
|
18
|
+
key.nil? ? @context.local : @context.local(key)
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -43,8 +43,9 @@ module Datadog
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Return the thread-local context.
|
|
46
|
-
def local
|
|
47
|
-
Thread.
|
|
46
|
+
def local(thread = Thread.current)
|
|
47
|
+
raise ArgumentError, '\'thread\' must be a Thread.' unless thread.is_a?(Thread)
|
|
48
|
+
thread[@key] ||= Datadog::Context.new
|
|
48
49
|
end
|
|
49
50
|
end
|
|
50
51
|
end
|
|
@@ -10,7 +10,9 @@ module Datadog
|
|
|
10
10
|
ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_DELAYED_JOB_ANALYTICS_SAMPLE_RATE'.freeze
|
|
11
11
|
ENV_ANALYTICS_SAMPLE_RATE_OLD = 'DD_DELAYED_JOB_ANALYTICS_SAMPLE_RATE'.freeze
|
|
12
12
|
SERVICE_NAME = 'delayed_job'.freeze
|
|
13
|
+
CLIENT_SERVICE_NAME = 'delayed_job-client'.freeze
|
|
13
14
|
SPAN_JOB = 'delayed_job'.freeze
|
|
15
|
+
SPAN_ENQUEUE = 'delayed_job.enqueue'.freeze
|
|
14
16
|
TAG_ATTEMPTS = 'delayed_job.attempts'.freeze
|
|
15
17
|
TAG_ID = 'delayed_job.id'.freeze
|
|
16
18
|
TAG_PRIORITY = 'delayed_job.priority'.freeze
|
|
@@ -7,22 +7,11 @@ module Datadog
|
|
|
7
7
|
module DelayedJob
|
|
8
8
|
# DelayedJob plugin that instruments invoke_job hook
|
|
9
9
|
class Plugin < Delayed::Plugin
|
|
10
|
-
def self.
|
|
10
|
+
def self.instrument_invoke(job, &block)
|
|
11
11
|
return block.call(job) unless tracer && tracer.enabled
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
job_name = if job.payload_object.respond_to?(:job_data)
|
|
16
|
-
job.payload_object.job_data['job_class']
|
|
17
|
-
else
|
|
18
|
-
job.name
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
tracer.trace(Ext::SPAN_JOB, service: configuration[:service_name], resource: job_name) do |span|
|
|
22
|
-
# Set analytics sample rate
|
|
23
|
-
if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
|
|
24
|
-
Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
|
|
25
|
-
end
|
|
13
|
+
tracer.trace(Ext::SPAN_JOB, service: configuration[:service_name], resource: job_name(job)) do |span|
|
|
14
|
+
set_sample_rate(span)
|
|
26
15
|
|
|
27
16
|
# Measure service stats
|
|
28
17
|
Contrib::Analytics.set_measured(span)
|
|
@@ -37,6 +26,23 @@ module Datadog
|
|
|
37
26
|
end
|
|
38
27
|
end
|
|
39
28
|
|
|
29
|
+
def self.instrument_enqueue(job, &block)
|
|
30
|
+
return block.call(job) unless tracer && tracer.enabled
|
|
31
|
+
|
|
32
|
+
tracer.trace(Ext::SPAN_ENQUEUE, service: configuration[:client_service_name], resource: job_name(job)) do |span|
|
|
33
|
+
set_sample_rate(span)
|
|
34
|
+
|
|
35
|
+
# Measure service stats
|
|
36
|
+
Contrib::Analytics.set_measured(span)
|
|
37
|
+
|
|
38
|
+
span.set_tag(Ext::TAG_QUEUE, job.queue) if job.queue
|
|
39
|
+
span.set_tag(Ext::TAG_PRIORITY, job.priority)
|
|
40
|
+
span.span_type = Datadog::Ext::AppTypes::WORKER
|
|
41
|
+
|
|
42
|
+
yield job
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
40
46
|
def self.flush(worker, &block)
|
|
41
47
|
yield worker
|
|
42
48
|
|
|
@@ -51,8 +57,24 @@ module Datadog
|
|
|
51
57
|
configuration[:tracer]
|
|
52
58
|
end
|
|
53
59
|
|
|
60
|
+
def self.job_name(job)
|
|
61
|
+
# When DelayedJob is used through ActiveJob, we need to parse the payload differentely
|
|
62
|
+
# to get the actual job name
|
|
63
|
+
return job.payload_object.job_data['job_class'] if job.payload_object.respond_to?(:job_data)
|
|
64
|
+
|
|
65
|
+
job.name
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.set_sample_rate(span)
|
|
69
|
+
# Set analytics sample rate
|
|
70
|
+
if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
|
|
71
|
+
Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
54
75
|
callbacks do |lifecycle|
|
|
55
|
-
lifecycle.around(:invoke_job, &method(:
|
|
76
|
+
lifecycle.around(:invoke_job, &method(:instrument_invoke))
|
|
77
|
+
lifecycle.around(:enqueue, &method(:instrument_enqueue))
|
|
56
78
|
lifecycle.around(:execute, &method(:flush))
|
|
57
79
|
end
|
|
58
80
|
end
|
|
@@ -8,7 +8,7 @@ module Datadog
|
|
|
8
8
|
module GRPC
|
|
9
9
|
module DatadogInterceptor
|
|
10
10
|
# The DatadogInterceptor::Client implements the tracing strategy
|
|
11
|
-
# for gRPC client-side
|
|
11
|
+
# for gRPC client-side endpoints. This middleware component will
|
|
12
12
|
# inject trace context information into gRPC metadata prior to
|
|
13
13
|
# sending the request to the server.
|
|
14
14
|
class Client < Base
|
|
@@ -54,14 +54,25 @@ module Datadog
|
|
|
54
54
|
|
|
55
55
|
def add_logger(app)
|
|
56
56
|
# check if lograge key exists
|
|
57
|
-
|
|
57
|
+
# Note: Rails executes initializers sequentially based on alphabetical order,
|
|
58
|
+
# and lograge config could occur after dd config.
|
|
59
|
+
# Checking for `app.config.lograge.enabled` may yield a false negative.
|
|
60
|
+
# Instead we should naively add custom options if `config.lograge` exists from the lograge Railtie,
|
|
61
|
+
# since the custom options get ignored without lograge explicitly being enabled.
|
|
62
|
+
# See: https://github.com/roidrage/lograge/blob/1729eab7956bb95c5992e4adab251e4f93ff9280/lib/lograge/railtie.rb#L7-L12
|
|
63
|
+
if app.config.respond_to?(:lograge)
|
|
58
64
|
Datadog::Contrib::Rails::LogInjection.add_lograge_logger(app)
|
|
59
|
-
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# if lograge isn't set, check if tagged logged is enabled.
|
|
60
68
|
# if so, add proc that injects trace identifiers for tagged logging.
|
|
61
|
-
|
|
69
|
+
if (logger = app.config.logger) &&
|
|
70
|
+
defined?(::ActiveSupport::TaggedLogging) &&
|
|
71
|
+
logger.is_a?(::ActiveSupport::TaggedLogging)
|
|
72
|
+
|
|
62
73
|
Datadog::Contrib::Rails::LogInjection.add_as_tagged_logging_logger(app)
|
|
63
74
|
else
|
|
64
|
-
Datadog.logger.warn("
|
|
75
|
+
Datadog.logger.warn("Unable to enable Datadog Trace context, Logger #{logger} is not supported")
|
|
65
76
|
end
|
|
66
77
|
end
|
|
67
78
|
|
|
@@ -11,7 +11,7 @@ module Datadog
|
|
|
11
11
|
|
|
12
12
|
MINIMUM_VERSION = Gem::Version.new('1.0')
|
|
13
13
|
# Maximum is first version it's NOT compatible with (not inclusive)
|
|
14
|
-
MAXIMUM_VERSION = Gem::Version.new('
|
|
14
|
+
MAXIMUM_VERSION = Gem::Version.new('3.0')
|
|
15
15
|
|
|
16
16
|
register_as :resque, auto_patch: true
|
|
17
17
|
|
|
@@ -38,24 +38,36 @@ module Datadog
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def trace_id
|
|
41
|
-
value =
|
|
41
|
+
value = metadata_for_key(GRPC_METADATA_TRACE_ID).to_i
|
|
42
42
|
value if (1..Span::EXTERNAL_MAX_ID).cover? value
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def parent_id
|
|
46
|
-
value =
|
|
46
|
+
value = metadata_for_key(GRPC_METADATA_PARENT_ID).to_i
|
|
47
47
|
value if (1..Span::EXTERNAL_MAX_ID).cover? value
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def sampling_priority
|
|
51
|
-
value =
|
|
51
|
+
value = metadata_for_key(GRPC_METADATA_SAMPLING_PRIORITY)
|
|
52
52
|
value && value.to_i
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def origin
|
|
56
|
-
value =
|
|
56
|
+
value = metadata_for_key(GRPC_METADATA_ORIGIN)
|
|
57
57
|
value if value != ''
|
|
58
58
|
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def metadata_for_key(key)
|
|
63
|
+
# metadata values can be arrays (multiple headers with the same key)
|
|
64
|
+
value = @metadata[key]
|
|
65
|
+
if value.is_a?(Array)
|
|
66
|
+
value.first
|
|
67
|
+
else
|
|
68
|
+
value
|
|
69
|
+
end
|
|
70
|
+
end
|
|
59
71
|
end
|
|
60
72
|
end
|
|
61
73
|
end
|
data/lib/ddtrace/tracer.rb
CHANGED
|
@@ -59,8 +59,8 @@ module Datadog
|
|
|
59
59
|
#
|
|
60
60
|
# This method makes use of a \ContextProvider that is automatically set during the tracer
|
|
61
61
|
# initialization, or while using a library instrumentation.
|
|
62
|
-
def call_context
|
|
63
|
-
@provider.context
|
|
62
|
+
def call_context(key = nil)
|
|
63
|
+
@provider.context(key)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# Initialize a new \Tracer used to create, sample and submit spans that measure the
|
|
@@ -324,18 +324,18 @@ module Datadog
|
|
|
324
324
|
end
|
|
325
325
|
|
|
326
326
|
# Return the current active span or +nil+.
|
|
327
|
-
def active_span
|
|
328
|
-
call_context.current_span
|
|
327
|
+
def active_span(key = nil)
|
|
328
|
+
call_context(key).current_span
|
|
329
329
|
end
|
|
330
330
|
|
|
331
331
|
# Return the current active root span or +nil+.
|
|
332
|
-
def active_root_span
|
|
333
|
-
call_context.current_root_span
|
|
332
|
+
def active_root_span(key = nil)
|
|
333
|
+
call_context(key).current_root_span
|
|
334
334
|
end
|
|
335
335
|
|
|
336
336
|
# Return a CorrelationIdentifier for active span
|
|
337
|
-
def active_correlation
|
|
338
|
-
Datadog::Correlation.identifier_from_context(call_context)
|
|
337
|
+
def active_correlation(key = nil)
|
|
338
|
+
Datadog::Correlation.identifier_from_context(call_context(key))
|
|
339
339
|
end
|
|
340
340
|
|
|
341
341
|
# Send the trace to the writer to enqueue the spans list in the agent
|
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.42.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: 2020-
|
|
11
|
+
date: 2020-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: msgpack
|
|
@@ -122,6 +122,20 @@ dependencies:
|
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '1.1'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: ruby-prof
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '1.4'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '1.4'
|
|
125
139
|
- !ruby/object:Gem::Dependency
|
|
126
140
|
name: minitest
|
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|