ddtrace 1.18.0 → 1.20.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 +82 -1
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +96 -66
- data/ext/ddtrace_profiling_native_extension/collectors_discrete_dynamic_sampler.c +349 -0
- data/ext/ddtrace_profiling_native_extension/collectors_discrete_dynamic_sampler.h +89 -0
- data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.c +22 -14
- data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.h +4 -0
- data/ext/ddtrace_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
- data/ext/ddtrace_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
- data/ext/ddtrace_profiling_native_extension/collectors_stack.c +43 -102
- data/ext/ddtrace_profiling_native_extension/collectors_stack.h +10 -3
- data/ext/ddtrace_profiling_native_extension/collectors_thread_context.c +159 -124
- data/ext/ddtrace_profiling_native_extension/collectors_thread_context.h +2 -1
- data/ext/ddtrace_profiling_native_extension/extconf.rb +19 -0
- data/ext/ddtrace_profiling_native_extension/heap_recorder.c +970 -0
- data/ext/ddtrace_profiling_native_extension/heap_recorder.h +155 -0
- data/ext/ddtrace_profiling_native_extension/helpers.h +6 -0
- data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.c +20 -0
- data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +11 -0
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +5 -0
- data/ext/ddtrace_profiling_native_extension/profiling.c +17 -0
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +147 -0
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +28 -0
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +329 -10
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +3 -0
- data/ext/ddtrace_profiling_native_extension/time_helpers.h +2 -0
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +2 -1
- data/lib/datadog/core/configuration/settings.rb +153 -21
- data/lib/datadog/core/environment/class_count.rb +6 -6
- data/lib/datadog/core/remote/component.rb +25 -12
- data/lib/datadog/core/remote/ext.rb +1 -0
- data/lib/datadog/core/remote/tie/tracing.rb +39 -0
- data/lib/datadog/core/remote/tie.rb +27 -0
- data/lib/datadog/core/telemetry/collector.rb +10 -0
- data/lib/datadog/core/telemetry/event.rb +2 -1
- data/lib/datadog/core/telemetry/ext.rb +3 -0
- data/lib/datadog/core/telemetry/v1/app_event.rb +8 -1
- data/lib/datadog/core/telemetry/v1/install_signature.rb +38 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -2
- data/lib/datadog/opentelemetry.rb +3 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -12
- data/lib/datadog/profiling/component.rb +183 -13
- data/lib/datadog/profiling/scheduler.rb +4 -6
- data/lib/datadog/profiling/stack_recorder.rb +13 -2
- data/lib/datadog/tracing/configuration/ext.rb +0 -1
- data/lib/datadog/tracing/configuration/settings.rb +2 -1
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_cable/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_mailer/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/action_view/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_job/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_record/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/active_support/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/analytics.rb +0 -1
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -0
- data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/grape/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +2 -2
- data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/kafka/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -1
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/qless/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/racecar/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +9 -2
- data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +0 -2
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rake/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/patcher.rb +34 -21
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/resque/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sequel/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/shoryuken/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/stripe/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +58 -0
- data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +94 -0
- data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing.rb +8 -2
- data/lib/ddtrace/version.rb +1 -1
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1baa733b2ad3335ab214de620e849f1eab598effb15d24f336aa20147e6e34be
|
4
|
+
data.tar.gz: 684bbf501475346f6e2a32b5a9284d59e193344e23d63b912624de77ac8bbbad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a10dcafb4ff9e9655e06e149ae83a872a0b614f44d69db15ed120f6aa6990f858bb94897d7b8fe30c1b41fe74dc71f054bdf7f0387ded0c0b66058d0d9a15492
|
7
|
+
data.tar.gz: 87be0dc85c2fc044a0f95096d147dbc79dda101babad85bfdfd29a37c42cd9cb70180fdedae00ff95321fe6eec0e4d61a6aaab852c9c6d3f10fc39ff7f06d87c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,54 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [1.20.0] - 2024-02-05
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Tracing: Add `Trilogy` instrumentation ([#3274][])
|
10
|
+
* Rack: Add remote configuration boot tags ([#3315][])
|
11
|
+
* Faraday: Add `on_error` option ([#3431][])
|
12
|
+
* Profiling: Add dynamic allocation sampling ([#3395][])
|
13
|
+
|
14
|
+
### Changed
|
15
|
+
|
16
|
+
* Bump `datadog-ci` dependency to 0.7.0 ([#3408][])
|
17
|
+
* Improve performance of gathering ClassCount metric ([#3386][])
|
18
|
+
|
19
|
+
### Fixed
|
20
|
+
|
21
|
+
* OpenTelemetry: Fix internal loading ([#3400][])
|
22
|
+
* Core: Fix logger deadlock ([#3426][])
|
23
|
+
* Rack: Fix missing active trace ([#3420][])
|
24
|
+
* Redis: Fix instance configuration ([#3278][])
|
25
|
+
|
26
|
+
## [1.19.0] - 2024-01-10
|
27
|
+
|
28
|
+
### Highlights
|
29
|
+
Alpha support for memory profiling has been added. For more details, check the [release notes](https://github.com/DataDog/dd-trace-rb/releases/tag/v1.19.0)
|
30
|
+
|
31
|
+
### Added
|
32
|
+
* Tracing: Add `on_error` settings for `mysql2` ([#3316][])
|
33
|
+
* Core: Add install_signature to app-started telemetry event ([#3349][])
|
34
|
+
* Profiling: Heap Profiling ([#3281][]) ([#3287][]) ([#3328][]) ([#3329][]) ([#3333][]) ([#3360][])
|
35
|
+
* Profiling: Redesign GC profiling to add timeline support and reduce overhead ([#3313][])
|
36
|
+
* Core: Use Ruby 3.3 stable for CI testing ([#3354][])
|
37
|
+
|
38
|
+
### Changed
|
39
|
+
* Core: Bump `datadog-ci` dependency to 0.6.0 ([#3361][])
|
40
|
+
* Core: Bump debase-ruby_core_source dependency to 3.3.1 ([#3373][])
|
41
|
+
* Docs: Backport "List Ruby 3.3 as supported in the docs" to master branch ([#3374][])
|
42
|
+
* Profiling: Import upstream `rb_profile_frames` fix ([#3352][])
|
43
|
+
* Profiling: Allow the dynamic sampling rate overhead target to be set ([#3310][])
|
44
|
+
* Profiling: Split profiling tests into ractor and non-ractor suites. ([#3320][])
|
45
|
+
|
46
|
+
### Fixed
|
47
|
+
* Docs: Fix `pg` doc markdown format ([#3317][])
|
48
|
+
* Tracing: Fix recursive `require` in Railtie ([#3365][])
|
49
|
+
* Profiling: Fix issues stemming from rb_gc_force_recycle ([#3366][])
|
50
|
+
* Profiling: Fix Ruby 3.3 CI being broken in master due to profiler ([#3356][])
|
51
|
+
* Profiling: Fix "no signals" workaround detection when mariadb is in use ([#3362][])
|
52
|
+
|
5
53
|
## [1.18.0] - 2023-12-07
|
6
54
|
|
7
55
|
### Added
|
@@ -2680,7 +2728,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
2680
2728
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
2681
2729
|
|
2682
2730
|
|
2683
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.
|
2731
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.20.0...master
|
2732
|
+
[1.20.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.19.0...v1.20.0
|
2733
|
+
[1.19.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.18.0...v1.19.0
|
2684
2734
|
[1.18.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.17.0...v1.18.0
|
2685
2735
|
[1.17.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.16.2...v1.17.0
|
2686
2736
|
[1.16.2]: https://github.com/DataDog/dd-trace-rb/compare/v1.16.1...v1.16.2
|
@@ -3908,14 +3958,45 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3908
3958
|
[#3270]: https://github.com/DataDog/dd-trace-rb/issues/3270
|
3909
3959
|
[#3271]: https://github.com/DataDog/dd-trace-rb/issues/3271
|
3910
3960
|
[#3273]: https://github.com/DataDog/dd-trace-rb/issues/3273
|
3961
|
+
[#3274]: https://github.com/DataDog/dd-trace-rb/issues/3274
|
3962
|
+
[#3278]: https://github.com/DataDog/dd-trace-rb/issues/3278
|
3911
3963
|
[#3279]: https://github.com/DataDog/dd-trace-rb/issues/3279
|
3912
3964
|
[#3280]: https://github.com/DataDog/dd-trace-rb/issues/3280
|
3965
|
+
[#3281]: https://github.com/DataDog/dd-trace-rb/issues/3281
|
3913
3966
|
[#3284]: https://github.com/DataDog/dd-trace-rb/issues/3284
|
3914
3967
|
[#3286]: https://github.com/DataDog/dd-trace-rb/issues/3286
|
3968
|
+
[#3287]: https://github.com/DataDog/dd-trace-rb/issues/3287
|
3915
3969
|
[#3289]: https://github.com/DataDog/dd-trace-rb/issues/3289
|
3916
3970
|
[#3303]: https://github.com/DataDog/dd-trace-rb/issues/3303
|
3917
3971
|
[#3307]: https://github.com/DataDog/dd-trace-rb/issues/3307
|
3918
3972
|
[#3308]: https://github.com/DataDog/dd-trace-rb/issues/3308
|
3973
|
+
[#3310]: https://github.com/DataDog/dd-trace-rb/issues/3310
|
3974
|
+
[#3313]: https://github.com/DataDog/dd-trace-rb/issues/3313
|
3975
|
+
[#3315]: https://github.com/DataDog/dd-trace-rb/issues/3315
|
3976
|
+
[#3316]: https://github.com/DataDog/dd-trace-rb/issues/3316
|
3977
|
+
[#3317]: https://github.com/DataDog/dd-trace-rb/issues/3317
|
3978
|
+
[#3320]: https://github.com/DataDog/dd-trace-rb/issues/3320
|
3979
|
+
[#3328]: https://github.com/DataDog/dd-trace-rb/issues/3328
|
3980
|
+
[#3329]: https://github.com/DataDog/dd-trace-rb/issues/3329
|
3981
|
+
[#3333]: https://github.com/DataDog/dd-trace-rb/issues/3333
|
3982
|
+
[#3349]: https://github.com/DataDog/dd-trace-rb/issues/3349
|
3983
|
+
[#3352]: https://github.com/DataDog/dd-trace-rb/issues/3352
|
3984
|
+
[#3354]: https://github.com/DataDog/dd-trace-rb/issues/3354
|
3985
|
+
[#3356]: https://github.com/DataDog/dd-trace-rb/issues/3356
|
3986
|
+
[#3360]: https://github.com/DataDog/dd-trace-rb/issues/3360
|
3987
|
+
[#3361]: https://github.com/DataDog/dd-trace-rb/issues/3361
|
3988
|
+
[#3362]: https://github.com/DataDog/dd-trace-rb/issues/3362
|
3989
|
+
[#3365]: https://github.com/DataDog/dd-trace-rb/issues/3365
|
3990
|
+
[#3366]: https://github.com/DataDog/dd-trace-rb/issues/3366
|
3991
|
+
[#3373]: https://github.com/DataDog/dd-trace-rb/issues/3373
|
3992
|
+
[#3374]: https://github.com/DataDog/dd-trace-rb/issues/3374
|
3993
|
+
[#3386]: https://github.com/DataDog/dd-trace-rb/issues/3386
|
3994
|
+
[#3395]: https://github.com/DataDog/dd-trace-rb/issues/3395
|
3995
|
+
[#3400]: https://github.com/DataDog/dd-trace-rb/issues/3400
|
3996
|
+
[#3408]: https://github.com/DataDog/dd-trace-rb/issues/3408
|
3997
|
+
[#3420]: https://github.com/DataDog/dd-trace-rb/issues/3420
|
3998
|
+
[#3426]: https://github.com/DataDog/dd-trace-rb/issues/3426
|
3999
|
+
[#3431]: https://github.com/DataDog/dd-trace-rb/issues/3431
|
3919
4000
|
[@AdrianLC]: https://github.com/AdrianLC
|
3920
4001
|
[@Azure7111]: https://github.com/Azure7111
|
3921
4002
|
[@BabyGroot]: https://github.com/BabyGroot
|
@@ -12,10 +12,14 @@
|
|
12
12
|
#include "collectors_thread_context.h"
|
13
13
|
#include "collectors_dynamic_sampling_rate.h"
|
14
14
|
#include "collectors_idle_sampling_helper.h"
|
15
|
+
#include "collectors_discrete_dynamic_sampler.h"
|
15
16
|
#include "private_vm_api_access.h"
|
16
17
|
#include "setup_signal_handler.h"
|
17
18
|
#include "time_helpers.h"
|
18
19
|
|
20
|
+
// Maximum allowed value for an allocation weight. Attempts to use higher values will result in clamping.
|
21
|
+
unsigned int MAX_ALLOC_WEIGHT = 65535;
|
22
|
+
|
19
23
|
// Used to trigger the execution of Collectors::ThreadState, which implements all of the sampling logic
|
20
24
|
// itself; this class only implements the "when to do it" part.
|
21
25
|
//
|
@@ -75,20 +79,27 @@
|
|
75
79
|
//
|
76
80
|
// ---
|
77
81
|
|
82
|
+
#ifndef NO_POSTPONED_TRIGGER
|
83
|
+
// Used to call the rb_postponed_job_trigger from Ruby 3.3+. These get initialized in
|
84
|
+
// `collectors_cpu_and_wall_time_worker_init` below and always get reused after that.
|
85
|
+
static rb_postponed_job_handle_t sample_from_postponed_job_handle;
|
86
|
+
static rb_postponed_job_handle_t after_gc_from_postponed_job_handle;
|
87
|
+
#endif
|
88
|
+
|
78
89
|
// Contains state for a single CpuAndWallTimeWorker instance
|
79
90
|
struct cpu_and_wall_time_worker_state {
|
80
91
|
// These are immutable after initialization
|
81
92
|
|
82
93
|
bool gc_profiling_enabled;
|
83
|
-
bool allocation_counting_enabled;
|
84
94
|
bool no_signals_workaround_enabled;
|
85
95
|
bool dynamic_sampling_rate_enabled;
|
86
|
-
|
96
|
+
bool allocation_profiling_enabled;
|
87
97
|
VALUE self_instance;
|
88
98
|
VALUE thread_context_collector_instance;
|
89
99
|
VALUE idle_sampling_helper_instance;
|
90
100
|
VALUE owner_thread;
|
91
|
-
dynamic_sampling_rate_state
|
101
|
+
dynamic_sampling_rate_state cpu_dynamic_sampling_rate;
|
102
|
+
discrete_dynamic_sampler allocation_sampler;
|
92
103
|
VALUE gc_tracepoint; // Used to get gc start/finish information
|
93
104
|
VALUE object_allocation_tracepoint; // Used to get allocation counts and allocation profiling
|
94
105
|
|
@@ -149,10 +160,10 @@ static VALUE _native_initialize(
|
|
149
160
|
VALUE thread_context_collector_instance,
|
150
161
|
VALUE gc_profiling_enabled,
|
151
162
|
VALUE idle_sampling_helper_instance,
|
152
|
-
VALUE allocation_counting_enabled,
|
153
163
|
VALUE no_signals_workaround_enabled,
|
154
164
|
VALUE dynamic_sampling_rate_enabled,
|
155
|
-
VALUE
|
165
|
+
VALUE dynamic_sampling_rate_overhead_target_percentage,
|
166
|
+
VALUE allocation_profiling_enabled
|
156
167
|
);
|
157
168
|
static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
|
158
169
|
static VALUE _native_sampling_loop(VALUE self, VALUE instance);
|
@@ -211,6 +222,16 @@ __thread uint64_t allocation_count = 0;
|
|
211
222
|
void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
212
223
|
rb_global_variable(&active_sampler_instance);
|
213
224
|
|
225
|
+
#ifndef NO_POSTPONED_TRIGGER
|
226
|
+
int unused_flags = 0;
|
227
|
+
sample_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, sample_from_postponed_job, NULL);
|
228
|
+
after_gc_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gc_from_postponed_job, NULL);
|
229
|
+
|
230
|
+
if (sample_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID || after_gc_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID) {
|
231
|
+
rb_raise(rb_eRuntimeError, "Failed to register profiler postponed jobs (got POSTPONED_JOB_HANDLE_INVALID)");
|
232
|
+
}
|
233
|
+
#endif
|
234
|
+
|
214
235
|
VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
|
215
236
|
VALUE collectors_cpu_and_wall_time_worker_class = rb_define_class_under(collectors_module, "CpuAndWallTimeWorker", rb_cObject);
|
216
237
|
// Hosts methods used for testing the native code using RSpec
|
@@ -264,14 +285,14 @@ static VALUE _native_new(VALUE klass) {
|
|
264
285
|
// being leaked.
|
265
286
|
|
266
287
|
state->gc_profiling_enabled = false;
|
267
|
-
state->allocation_counting_enabled = false;
|
268
288
|
state->no_signals_workaround_enabled = false;
|
269
289
|
state->dynamic_sampling_rate_enabled = true;
|
270
|
-
state->
|
290
|
+
state->allocation_profiling_enabled = false;
|
271
291
|
state->thread_context_collector_instance = Qnil;
|
272
292
|
state->idle_sampling_helper_instance = Qnil;
|
273
293
|
state->owner_thread = Qnil;
|
274
|
-
dynamic_sampling_rate_init(&state->
|
294
|
+
dynamic_sampling_rate_init(&state->cpu_dynamic_sampling_rate);
|
295
|
+
discrete_dynamic_sampler_init(&state->allocation_sampler, "allocation");
|
275
296
|
state->gc_tracepoint = Qnil;
|
276
297
|
state->object_allocation_tracepoint = Qnil;
|
277
298
|
|
@@ -292,28 +313,33 @@ static VALUE _native_initialize(
|
|
292
313
|
VALUE thread_context_collector_instance,
|
293
314
|
VALUE gc_profiling_enabled,
|
294
315
|
VALUE idle_sampling_helper_instance,
|
295
|
-
VALUE allocation_counting_enabled,
|
296
316
|
VALUE no_signals_workaround_enabled,
|
297
317
|
VALUE dynamic_sampling_rate_enabled,
|
298
|
-
VALUE
|
318
|
+
VALUE dynamic_sampling_rate_overhead_target_percentage,
|
319
|
+
VALUE allocation_profiling_enabled
|
299
320
|
) {
|
300
321
|
ENFORCE_BOOLEAN(gc_profiling_enabled);
|
301
|
-
ENFORCE_BOOLEAN(allocation_counting_enabled);
|
302
322
|
ENFORCE_BOOLEAN(no_signals_workaround_enabled);
|
303
323
|
ENFORCE_BOOLEAN(dynamic_sampling_rate_enabled);
|
304
|
-
ENFORCE_TYPE(
|
324
|
+
ENFORCE_TYPE(dynamic_sampling_rate_overhead_target_percentage, T_FLOAT);
|
325
|
+
ENFORCE_BOOLEAN(allocation_profiling_enabled);
|
305
326
|
|
306
327
|
struct cpu_and_wall_time_worker_state *state;
|
307
328
|
TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
308
329
|
|
309
330
|
state->gc_profiling_enabled = (gc_profiling_enabled == Qtrue);
|
310
|
-
state->allocation_counting_enabled = (allocation_counting_enabled == Qtrue);
|
311
331
|
state->no_signals_workaround_enabled = (no_signals_workaround_enabled == Qtrue);
|
312
332
|
state->dynamic_sampling_rate_enabled = (dynamic_sampling_rate_enabled == Qtrue);
|
313
|
-
state->
|
333
|
+
state->allocation_profiling_enabled = (allocation_profiling_enabled == Qtrue);
|
314
334
|
|
315
|
-
|
316
|
-
|
335
|
+
double total_overhead_target_percentage = NUM2DBL(dynamic_sampling_rate_overhead_target_percentage);
|
336
|
+
if (!state->allocation_profiling_enabled) {
|
337
|
+
dynamic_sampling_rate_set_overhead_target_percentage(&state->cpu_dynamic_sampling_rate, total_overhead_target_percentage);
|
338
|
+
} else {
|
339
|
+
// TODO: May be nice to offer customization here? Distribute available "overhead" margin with a bias towards one or the other
|
340
|
+
// sampler.
|
341
|
+
dynamic_sampling_rate_set_overhead_target_percentage(&state->cpu_dynamic_sampling_rate, total_overhead_target_percentage / 2);
|
342
|
+
discrete_dynamic_sampler_set_overhead_target_percentage(&state->allocation_sampler, total_overhead_target_percentage / 2);
|
317
343
|
}
|
318
344
|
|
319
345
|
state->thread_context_collector_instance = enforce_thread_context_collector_instance(thread_context_collector_instance);
|
@@ -366,7 +392,8 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
366
392
|
if (state->stop_thread == rb_thread_current()) return Qnil;
|
367
393
|
|
368
394
|
// Reset the dynamic sampling rate state, if any (reminder: the monotonic clock reference may change after a fork)
|
369
|
-
dynamic_sampling_rate_reset(&state->
|
395
|
+
dynamic_sampling_rate_reset(&state->cpu_dynamic_sampling_rate);
|
396
|
+
discrete_dynamic_sampler_reset(&state->allocation_sampler);
|
370
397
|
|
371
398
|
// This write to a global is thread-safe BECAUSE we're still holding on to the global VM lock at this point
|
372
399
|
active_sampler_instance_state = state;
|
@@ -472,20 +499,25 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
472
499
|
|
473
500
|
// Note: If we ever want to get rid of rb_postponed_job_register_one, remember not to clobber Ruby exceptions, as
|
474
501
|
// this function does this helpful job for us now -- https://github.com/ruby/ruby/commit/a98e343d39c4d7bf1e2190b076720f32d9f298b3.
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
502
|
+
#ifndef NO_POSTPONED_TRIGGER // Ruby 3.3+
|
503
|
+
rb_postponed_job_trigger(sample_from_postponed_job_handle);
|
504
|
+
state->stats.postponed_job_success++; // Always succeeds
|
505
|
+
#else
|
506
|
+
int result = rb_postponed_job_register_one(0, sample_from_postponed_job, NULL);
|
507
|
+
|
508
|
+
// Officially, the result of rb_postponed_job_register_one is documented as being opaque, but in practice it does not
|
509
|
+
// seem to have changed between Ruby 2.3 and 3.2, and so we track it as a debugging mechanism
|
510
|
+
switch (result) {
|
511
|
+
case 0:
|
512
|
+
state->stats.postponed_job_full++; break;
|
513
|
+
case 1:
|
514
|
+
state->stats.postponed_job_success++; break;
|
515
|
+
case 2:
|
516
|
+
state->stats.postponed_job_skipped_already_existed++; break;
|
517
|
+
default:
|
518
|
+
state->stats.postponed_job_unknown_result++;
|
519
|
+
}
|
520
|
+
#endif
|
489
521
|
}
|
490
522
|
|
491
523
|
// The actual sampling trigger loop always runs **without** the global vm lock.
|
@@ -534,7 +566,7 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
534
566
|
// Note that we deliberately should NOT combine this sleep_for with the one above because the result of
|
535
567
|
// `dynamic_sampling_rate_get_sleep` may have changed while the above sleep was ongoing.
|
536
568
|
uint64_t extra_sleep =
|
537
|
-
dynamic_sampling_rate_get_sleep(&state->
|
569
|
+
dynamic_sampling_rate_get_sleep(&state->cpu_dynamic_sampling_rate, monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE));
|
538
570
|
if (state->dynamic_sampling_rate_enabled && extra_sleep > 0) sleep_for(extra_sleep);
|
539
571
|
}
|
540
572
|
|
@@ -574,7 +606,7 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
574
606
|
|
575
607
|
long wall_time_ns_before_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
|
576
608
|
|
577
|
-
if (state->dynamic_sampling_rate_enabled && !dynamic_sampling_rate_should_sample(&state->
|
609
|
+
if (state->dynamic_sampling_rate_enabled && !dynamic_sampling_rate_should_sample(&state->cpu_dynamic_sampling_rate, wall_time_ns_before_sample)) {
|
578
610
|
state->stats.skipped_sample_because_of_dynamic_sampling_rate++;
|
579
611
|
return Qnil;
|
580
612
|
}
|
@@ -594,7 +626,7 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
594
626
|
state->stats.sampling_time_ns_max = uint64_max_of(sampling_time_ns, state->stats.sampling_time_ns_max);
|
595
627
|
state->stats.sampling_time_ns_total += sampling_time_ns;
|
596
628
|
|
597
|
-
dynamic_sampling_rate_after_sample(&state->
|
629
|
+
dynamic_sampling_rate_after_sample(&state->cpu_dynamic_sampling_rate, wall_time_ns_after_sample, sampling_time_ns);
|
598
630
|
|
599
631
|
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
600
632
|
return Qnil;
|
@@ -632,7 +664,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
632
664
|
// because they may raise exceptions.
|
633
665
|
install_sigprof_signal_handler(handle_sampling_signal, "handle_sampling_signal");
|
634
666
|
if (state->gc_profiling_enabled) rb_tracepoint_enable(state->gc_tracepoint);
|
635
|
-
if (state->
|
667
|
+
if (state->allocation_profiling_enabled) rb_tracepoint_enable(state->object_allocation_tracepoint);
|
636
668
|
|
637
669
|
rb_thread_call_without_gvl(run_sampling_trigger_loop, state, interrupt_sampling_trigger_loop, state);
|
638
670
|
|
@@ -714,28 +746,17 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
|
|
714
746
|
if (event == RUBY_INTERNAL_EVENT_GC_ENTER) {
|
715
747
|
thread_context_collector_on_gc_start(state->thread_context_collector_instance);
|
716
748
|
} else if (event == RUBY_INTERNAL_EVENT_GC_EXIT) {
|
717
|
-
|
718
|
-
|
719
|
-
//
|
720
|
-
//
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
// making the sampling process allocation-safe (very hard); or separate stack sampling from sample recording,
|
729
|
-
// e.g. enabling us to capture the stack in thread_context_collector_on_gc_finish and do the rest later
|
730
|
-
// (medium hard).
|
731
|
-
|
732
|
-
thread_context_collector_on_gc_finish(state->thread_context_collector_instance);
|
733
|
-
// We use rb_postponed_job_register_one to ask Ruby to run thread_context_collector_sample_after_gc after if
|
734
|
-
// fully finishes the garbage collection, so that one is allowed to do allocations and throw exceptions as usual.
|
735
|
-
//
|
736
|
-
// Note: If we ever want to get rid of rb_postponed_job_register_one, remember not to clobber Ruby exceptions, as
|
737
|
-
// this function does this helpful job for us now -- https://github.com/ruby/ruby/commit/a98e343d39c4d7bf1e2190b076720f32d9f298b3.
|
738
|
-
rb_postponed_job_register_one(0, after_gc_from_postponed_job, NULL);
|
749
|
+
bool should_flush = thread_context_collector_on_gc_finish(state->thread_context_collector_instance);
|
750
|
+
|
751
|
+
// We use rb_postponed_job_register_one to ask Ruby to run thread_context_collector_sample_after_gc when the
|
752
|
+
// thread collector flags it's time to flush.
|
753
|
+
if (should_flush) {
|
754
|
+
#ifndef NO_POSTPONED_TRIGGER // Ruby 3.3+
|
755
|
+
rb_postponed_job_trigger(after_gc_from_postponed_job_handle);
|
756
|
+
#else
|
757
|
+
rb_postponed_job_register_one(0, after_gc_from_postponed_job, NULL);
|
758
|
+
#endif
|
759
|
+
}
|
739
760
|
}
|
740
761
|
}
|
741
762
|
|
@@ -888,9 +909,9 @@ static void sleep_for(uint64_t time_ns) {
|
|
888
909
|
}
|
889
910
|
|
890
911
|
static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
|
891
|
-
bool
|
912
|
+
bool are_allocations_being_tracked = active_sampler_instance_state != NULL && active_sampler_instance_state->allocation_profiling_enabled;
|
892
913
|
|
893
|
-
return
|
914
|
+
return are_allocations_being_tracked ? ULL2NUM(allocation_count) : Qnil;
|
894
915
|
}
|
895
916
|
|
896
917
|
// Implements memory-related profiling events. This function is called by Ruby via the `object_allocation_tracepoint`
|
@@ -916,18 +937,20 @@ static void on_newobj_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused)
|
|
916
937
|
return;
|
917
938
|
}
|
918
939
|
|
940
|
+
if (state->dynamic_sampling_rate_enabled && !discrete_dynamic_sampler_should_sample(&state->allocation_sampler)) {
|
941
|
+
return;
|
942
|
+
}
|
943
|
+
|
919
944
|
// @ivoanjo: Strictly speaking, this is not needed because Ruby should not call the same tracepoint while a previous
|
920
945
|
// invocation is still pending, (e.g. it wouldn't call `on_newobj_event` while it's already running), but I decided
|
921
946
|
// to keep this here for consistency -- every call to the thread context (other than the special gc calls which are
|
922
947
|
// defined as not being able to allocate) sets this.
|
923
948
|
state->during_sample = true;
|
924
949
|
|
925
|
-
//
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
safely_call(rescued_sample_allocation, tracepoint_data, state->self_instance);
|
930
|
-
}
|
950
|
+
// Rescue against any exceptions that happen during sampling
|
951
|
+
safely_call(rescued_sample_allocation, tracepoint_data, state->self_instance);
|
952
|
+
|
953
|
+
discrete_dynamic_sampler_after_sample(&state->allocation_sampler);
|
931
954
|
|
932
955
|
state->during_sample = false;
|
933
956
|
}
|
@@ -959,7 +982,14 @@ static VALUE rescued_sample_allocation(VALUE tracepoint_data) {
|
|
959
982
|
rb_trace_arg_t *data = rb_tracearg_from_tracepoint(tracepoint_data);
|
960
983
|
VALUE new_object = rb_tracearg_object(data);
|
961
984
|
|
962
|
-
|
985
|
+
unsigned long allocations_since_last_sample = state->dynamic_sampling_rate_enabled ?
|
986
|
+
// if we're doing dynamic sampling, ask the sampler how many events since last sample
|
987
|
+
discrete_dynamic_sampler_events_since_last_sample(&state->allocation_sampler) :
|
988
|
+
// if we aren't, then we're sampling every event
|
989
|
+
1;
|
990
|
+
// TODO: Signal in the profile that clamping happened?
|
991
|
+
unsigned int weight = allocations_since_last_sample > MAX_ALLOC_WEIGHT ? MAX_ALLOC_WEIGHT : (unsigned int) allocations_since_last_sample;
|
992
|
+
thread_context_collector_sample_allocation(state->thread_context_collector_instance, weight, new_object);
|
963
993
|
|
964
994
|
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
965
995
|
return Qnil;
|