datadog 2.1.0 → 2.3.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/CHANGELOG.md +101 -1
- data/ext/datadog_profiling_loader/extconf.rb +15 -15
- data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +132 -44
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +90 -37
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +69 -62
- data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
- data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/helpers.h +6 -17
- data/ext/datadog_profiling_native_extension/http_transport.c +3 -3
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -126
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
- data/ext/datadog_profiling_native_extension/profiling.c +0 -2
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +27 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
- data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
- data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +20 -7
- data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
- data/ext/libdatadog_api/extconf.rb +108 -0
- data/ext/libdatadog_api/macos_development.md +26 -0
- data/ext/libdatadog_extconf_helpers.rb +130 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +1 -0
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +17 -12
- data/lib/datadog/core/configuration/settings.rb +93 -7
- data/lib/datadog/core/configuration.rb +3 -17
- data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
- data/lib/datadog/core/crashtracking/component.rb +111 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
- data/lib/datadog/core/deprecations.rb +58 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +6 -0
- data/lib/datadog/core/telemetry/component.rb +154 -0
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +132 -26
- data/lib/datadog/core/telemetry/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +11 -13
- data/lib/datadog/core/telemetry/http/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/transport.rb +38 -9
- data/lib/datadog/core/telemetry/logging.rb +35 -0
- data/lib/datadog/core/telemetry/metric.rb +167 -0
- data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
- data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
- data/lib/datadog/core/telemetry/request.rb +1 -1
- data/lib/datadog/core/telemetry/worker.rb +173 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/only_once_successful.rb +76 -0
- data/lib/datadog/core.rb +2 -19
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +24 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +3 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
- data/lib/datadog/profiling/component.rb +85 -90
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +8 -6
- data/lib/datadog/profiling/load_native_extension.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +5 -8
- data/lib/datadog/profiling/scheduler.rb +31 -25
- data/lib/datadog/profiling/tag_builder.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +5 -5
- data/lib/datadog/profiling/tasks/setup.rb +16 -35
- data/lib/datadog/profiling.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -1
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
- data/lib/datadog/tracing/contrib/analytics.rb +5 -0
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
- data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
- data/lib/datadog/tracing/distributed/datadog.rb +2 -2
- data/lib/datadog/tracing/distributed/propagation.rb +9 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +3 -2
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/span.rb +9 -2
- data/lib/datadog/tracing/span_event.rb +41 -0
- data/lib/datadog/tracing/span_operation.rb +9 -4
- data/lib/datadog/tracing/trace_operation.rb +7 -3
- data/lib/datadog/tracing/trace_segment.rb +4 -1
- data/lib/datadog/tracing/tracer.rb +9 -2
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing.rb +5 -1
- data/lib/datadog/version.rb +2 -2
- metadata +43 -12
- data/lib/datadog/core/telemetry/client.rb +0 -95
- data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d6610c8ef7e86c023f8a3fca884807bd7e9cf6b84fc6cbdd79b98e8a8762c2e
|
4
|
+
data.tar.gz: 236fafc4b8e2c809552d97c8eb025654c0ef4279685c741ad9504b2af8265b94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e633db76f69b5d151629cde5e1b7024a6bea43343aa348ea50857d5e74d049d2b6a833be252c6c1c7aee95976805a795e1607a81d42e8c3246126abd9811777d
|
7
|
+
data.tar.gz: fb2bcf3803689d8e499f2266e7d063f1c5b9b7d08bb28b5d27f81bd16e7e373c01c1d5224027d43229a5ca609f66c5179aa521ef272f347d069ca73e3613bdc3
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,64 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [2.3.0] - 2024-08-22
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Core: Support agentless telemetry ([#3779][])
|
10
|
+
* Tracing: Add support for span events ([#3776][])
|
11
|
+
* Tracing: Add tags to enable inferred service dependencies for databases ([#3789][])
|
12
|
+
* Tracing: Emit log message and instructions for incompatible Lograge setup ([#3812][], [#3839][])
|
13
|
+
* Tracing: Add `append_comment` option to append SQL comment propagation for `mysql`, `pg` and `trilogy` ([#3809][])
|
14
|
+
* AppSec: Add threat detection and protection for `graphql` ([#3769][], [#3814][])
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
|
18
|
+
* Core: Enable crashtracking by default ([#3826][])
|
19
|
+
* Profiling: Reduce allocation overhead ([#3805][], [#3797][])
|
20
|
+
* Profiling: Speed up stack sampling ([#3837][])
|
21
|
+
* Profiling: Upgrade to libdatadog 11 ([#3799][])
|
22
|
+
* Profiling: Disable allocation counting feature by default ([#3798][])
|
23
|
+
* Profiling: Reduce the maximum biased result for allocation samples ([#3793][])
|
24
|
+
* Tracing: Reduce noisy integration logs ([#3785][])
|
25
|
+
|
26
|
+
### Fixed
|
27
|
+
|
28
|
+
* Tracing: Fix `require` issue for `graphql` ([#3813][])
|
29
|
+
* AppSec: Fix an error when parsing http headers with integer value ([#3790][])
|
30
|
+
* AppSec: Fix an error when tracking login failure without `user_id` ([#3841][])
|
31
|
+
* Fix a syntax error for Ruby < 2.4 during single step instrumentation ([#3795][])
|
32
|
+
|
33
|
+
## [2.2.0] - 2024-07-11
|
34
|
+
|
35
|
+
### Added
|
36
|
+
|
37
|
+
* Tracing: Add `Rails` Runner instrumentation ([#2509][])
|
38
|
+
* Tracing: Introduce a new, reworked `GraphQL` tracer to comply with span attributes specification ([#3672][])
|
39
|
+
* Tracing: Enhance `ActiveSupport::Cache` instrumentation with `ActiveSupport::Notifications` subscription ([#3772][])
|
40
|
+
* Profiling: Track unscaled allocation counts in allocation profiler ([#3770][])
|
41
|
+
|
42
|
+
### Changed
|
43
|
+
|
44
|
+
* Core: Send Telemetry events in batches ([#3749][])
|
45
|
+
* Tracing: Populate spans from `ActiveSupport::Notifications` as early as possible ([#3725][])
|
46
|
+
* Profiling: Upgrade to `libdatadog` 10 ([#3753][])
|
47
|
+
* Profiling: Optimize `CodeProvenance#record_loaded_files` to avoid allocations ([#3757][])
|
48
|
+
|
49
|
+
### Fixed
|
50
|
+
|
51
|
+
* Core: Fix Telemetry events blocking main thread ([#3718][])
|
52
|
+
* Core: Fix deadlock from Telemetry threads ([#3743][])
|
53
|
+
* Tracing: Fix empty log correlation when tracing is disabled ([#3731][])
|
54
|
+
* Tracing: Fix HTTP propagation when missing parent span id ([#3730][])
|
55
|
+
* Tracing: Ensure `_dd.p.tid` tag with fixed size ([#3729][])
|
56
|
+
* OTel: Fix ids encoding/decoding for propagation ([#3709][])
|
57
|
+
* Profiling: Workaround Ruby `Dir` returning incorrect results ([#3720][])
|
58
|
+
* Profiling: Fix `Phusion Passenger` detection when missing from `Gemfile`/`gems.rb` ([#3750][])
|
59
|
+
* Profiling: Fix `rpath` for linking to libdatadog when loading extension ([#3706][])
|
60
|
+
* Profiling: Fix incorrect code provenance due to broken JSON monkey patch ([#3695][])
|
61
|
+
* Profiling: Fix aggregation of actionview template classes ([#3759][], [#3774][])
|
62
|
+
|
5
63
|
## [2.1.0] - 2024-06-10
|
6
64
|
|
7
65
|
### Added
|
@@ -2904,7 +2962,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
2904
2962
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
2905
2963
|
|
2906
2964
|
|
2907
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
2965
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.3.0...master
|
2966
|
+
[2.3.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.2.0...v2.3.0
|
2967
|
+
[2.2.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.1.0...v2.2.0
|
2908
2968
|
[2.1.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0...v2.1.0
|
2909
2969
|
[2.0.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0.rc1...v2.0.0
|
2910
2970
|
[2.0.0.rc1]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0.beta2...v2.0.0.rc1
|
@@ -3901,6 +3961,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3901
3961
|
[#2497]: https://github.com/DataDog/dd-trace-rb/issues/2497
|
3902
3962
|
[#2501]: https://github.com/DataDog/dd-trace-rb/issues/2501
|
3903
3963
|
[#2504]: https://github.com/DataDog/dd-trace-rb/issues/2504
|
3964
|
+
[#2509]: https://github.com/DataDog/dd-trace-rb/issues/2509
|
3904
3965
|
[#2512]: https://github.com/DataDog/dd-trace-rb/issues/2512
|
3905
3966
|
[#2513]: https://github.com/DataDog/dd-trace-rb/issues/2513
|
3906
3967
|
[#2522]: https://github.com/DataDog/dd-trace-rb/issues/2522
|
@@ -4283,6 +4344,45 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
4283
4344
|
[#3651]: https://github.com/DataDog/dd-trace-rb/issues/3651
|
4284
4345
|
[#3657]: https://github.com/DataDog/dd-trace-rb/issues/3657
|
4285
4346
|
[#3664]: https://github.com/DataDog/dd-trace-rb/issues/3664
|
4347
|
+
[#3672]: https://github.com/DataDog/dd-trace-rb/issues/3672
|
4348
|
+
[#3695]: https://github.com/DataDog/dd-trace-rb/issues/3695
|
4349
|
+
[#3706]: https://github.com/DataDog/dd-trace-rb/issues/3706
|
4350
|
+
[#3709]: https://github.com/DataDog/dd-trace-rb/issues/3709
|
4351
|
+
[#3718]: https://github.com/DataDog/dd-trace-rb/issues/3718
|
4352
|
+
[#3720]: https://github.com/DataDog/dd-trace-rb/issues/3720
|
4353
|
+
[#3725]: https://github.com/DataDog/dd-trace-rb/issues/3725
|
4354
|
+
[#3729]: https://github.com/DataDog/dd-trace-rb/issues/3729
|
4355
|
+
[#3730]: https://github.com/DataDog/dd-trace-rb/issues/3730
|
4356
|
+
[#3731]: https://github.com/DataDog/dd-trace-rb/issues/3731
|
4357
|
+
[#3743]: https://github.com/DataDog/dd-trace-rb/issues/3743
|
4358
|
+
[#3749]: https://github.com/DataDog/dd-trace-rb/issues/3749
|
4359
|
+
[#3750]: https://github.com/DataDog/dd-trace-rb/issues/3750
|
4360
|
+
[#3753]: https://github.com/DataDog/dd-trace-rb/issues/3753
|
4361
|
+
[#3757]: https://github.com/DataDog/dd-trace-rb/issues/3757
|
4362
|
+
[#3759]: https://github.com/DataDog/dd-trace-rb/issues/3759
|
4363
|
+
[#3769]: https://github.com/DataDog/dd-trace-rb/issues/3769
|
4364
|
+
[#3770]: https://github.com/DataDog/dd-trace-rb/issues/3770
|
4365
|
+
[#3772]: https://github.com/DataDog/dd-trace-rb/issues/3772
|
4366
|
+
[#3774]: https://github.com/DataDog/dd-trace-rb/issues/3774
|
4367
|
+
[#3776]: https://github.com/DataDog/dd-trace-rb/issues/3776
|
4368
|
+
[#3779]: https://github.com/DataDog/dd-trace-rb/issues/3779
|
4369
|
+
[#3785]: https://github.com/DataDog/dd-trace-rb/issues/3785
|
4370
|
+
[#3789]: https://github.com/DataDog/dd-trace-rb/issues/3789
|
4371
|
+
[#3790]: https://github.com/DataDog/dd-trace-rb/issues/3790
|
4372
|
+
[#3793]: https://github.com/DataDog/dd-trace-rb/issues/3793
|
4373
|
+
[#3795]: https://github.com/DataDog/dd-trace-rb/issues/3795
|
4374
|
+
[#3797]: https://github.com/DataDog/dd-trace-rb/issues/3797
|
4375
|
+
[#3798]: https://github.com/DataDog/dd-trace-rb/issues/3798
|
4376
|
+
[#3799]: https://github.com/DataDog/dd-trace-rb/issues/3799
|
4377
|
+
[#3805]: https://github.com/DataDog/dd-trace-rb/issues/3805
|
4378
|
+
[#3809]: https://github.com/DataDog/dd-trace-rb/issues/3809
|
4379
|
+
[#3812]: https://github.com/DataDog/dd-trace-rb/issues/3812
|
4380
|
+
[#3813]: https://github.com/DataDog/dd-trace-rb/issues/3813
|
4381
|
+
[#3814]: https://github.com/DataDog/dd-trace-rb/issues/3814
|
4382
|
+
[#3826]: https://github.com/DataDog/dd-trace-rb/issues/3826
|
4383
|
+
[#3837]: https://github.com/DataDog/dd-trace-rb/issues/3837
|
4384
|
+
[#3839]: https://github.com/DataDog/dd-trace-rb/issues/3839
|
4385
|
+
[#3841]: https://github.com/DataDog/dd-trace-rb/issues/3841
|
4286
4386
|
[@AdrianLC]: https://github.com/AdrianLC
|
4287
4387
|
[@Azure7111]: https://github.com/Azure7111
|
4288
4388
|
[@BabyGroot]: https://github.com/BabyGroot
|
@@ -1,22 +1,22 @@
|
|
1
1
|
# rubocop:disable Style/StderrPuts
|
2
2
|
# rubocop:disable Style/GlobalVars
|
3
3
|
|
4
|
-
if RUBY_ENGINE !=
|
4
|
+
if RUBY_ENGINE != "ruby" || Gem.win_platform?
|
5
5
|
$stderr.puts(
|
6
|
-
|
6
|
+
"WARN: Skipping build of Datadog profiling loader. See Datadog profiling native extension note for details."
|
7
7
|
)
|
8
8
|
|
9
|
-
File.write(
|
9
|
+
File.write("Makefile", "all install clean: # dummy makefile that does nothing")
|
10
10
|
exit
|
11
11
|
end
|
12
12
|
|
13
|
-
require
|
13
|
+
require "mkmf"
|
14
14
|
|
15
15
|
# mkmf on modern Rubies actually has an append_cflags that does something similar
|
16
16
|
# (see https://github.com/ruby/ruby/pull/5760), but as usual we need a bit more boilerplate to deal with legacy Rubies
|
17
17
|
def add_compiler_flag(flag)
|
18
18
|
if try_cflags(flag)
|
19
|
-
$CFLAGS <<
|
19
|
+
$CFLAGS << " " << flag
|
20
20
|
else
|
21
21
|
$stderr.puts("WARNING: '#{flag}' not accepted by compiler, skipping it")
|
22
22
|
end
|
@@ -24,26 +24,26 @@ end
|
|
24
24
|
|
25
25
|
# Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
|
26
26
|
# But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
|
27
|
-
add_compiler_flag
|
27
|
+
add_compiler_flag "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
|
28
28
|
|
29
29
|
# Older gcc releases may not default to C99 and we need to ask for this. This is also used:
|
30
30
|
# * by upstream Ruby -- search for gnu99 in the codebase
|
31
31
|
# * by msgpack, another datadog gem dependency
|
32
32
|
# (https://github.com/msgpack/msgpack-ruby/blob/18ce08f6d612fe973843c366ac9a0b74c4e50599/ext/msgpack/extconf.rb#L8)
|
33
|
-
add_compiler_flag
|
33
|
+
add_compiler_flag "-std=gnu99"
|
34
34
|
|
35
35
|
# Gets really noisy when we include the MJIT header, let's omit it (TODO: Use #pragma GCC diagnostic instead?)
|
36
|
-
add_compiler_flag
|
36
|
+
add_compiler_flag "-Wno-unused-function"
|
37
37
|
|
38
38
|
# Allow defining variables at any point in a function
|
39
|
-
add_compiler_flag
|
39
|
+
add_compiler_flag "-Wno-declaration-after-statement"
|
40
40
|
|
41
41
|
# If we forget to include a Ruby header, the function call may still appear to work, but then
|
42
42
|
# cause a segfault later. Let's ensure that never happens.
|
43
|
-
add_compiler_flag
|
43
|
+
add_compiler_flag "-Werror-implicit-function-declaration"
|
44
44
|
|
45
45
|
# Warn on unused parameters to functions. Use `DDTRACE_UNUSED` to mark things as known-to-not-be-used.
|
46
|
-
add_compiler_flag
|
46
|
+
add_compiler_flag "-Wunused-parameter"
|
47
47
|
|
48
48
|
# The native extension is not intended to expose any symbols/functions for other native libraries to use;
|
49
49
|
# the sole exception being `Init_datadog_profiling_loader` which needs to be visible for Ruby to call it when
|
@@ -51,14 +51,14 @@ add_compiler_flag '-Wunused-parameter'
|
|
51
51
|
#
|
52
52
|
# By setting this compiler flag, we tell it to assume that everything is private unless explicitly stated.
|
53
53
|
# For more details see https://gcc.gnu.org/wiki/Visibility
|
54
|
-
add_compiler_flag
|
54
|
+
add_compiler_flag "-fvisibility=hidden"
|
55
55
|
|
56
56
|
# Avoid legacy C definitions
|
57
|
-
add_compiler_flag
|
57
|
+
add_compiler_flag "-Wold-style-definition"
|
58
58
|
|
59
59
|
# Enable all other compiler warnings
|
60
|
-
add_compiler_flag
|
61
|
-
add_compiler_flag
|
60
|
+
add_compiler_flag "-Wall"
|
61
|
+
add_compiler_flag "-Wextra"
|
62
62
|
|
63
63
|
# Tag the native extension library with the Ruby version and Ruby platform.
|
64
64
|
# This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
|
@@ -7,11 +7,10 @@
|
|
7
7
|
#include <pthread.h>
|
8
8
|
#include <time.h>
|
9
9
|
#include <errno.h>
|
10
|
-
#include <ruby.h>
|
11
10
|
|
11
|
+
#include "clock_id.h"
|
12
12
|
#include "helpers.h"
|
13
13
|
#include "private_vm_api_access.h"
|
14
|
-
#include "clock_id.h"
|
15
14
|
#include "time_helpers.h"
|
16
15
|
|
17
16
|
// Validate that our home-cooked pthread_id_for() matches pthread_self() for the current thread
|
@@ -20,7 +20,9 @@
|
|
20
20
|
#define ERR_CLOCK_FAIL "failed to get clock time"
|
21
21
|
|
22
22
|
// Maximum allowed value for an allocation weight. Attempts to use higher values will result in clamping.
|
23
|
-
|
23
|
+
// See https://docs.google.com/document/d/1lWLB714wlLBBq6T4xZyAc4a5wtWhSmr4-hgiPKeErlA/edit#heading=h.ugp0zxcj5iqh
|
24
|
+
// (Datadog-only link) for research backing the choice of this value.
|
25
|
+
unsigned int MAX_ALLOC_WEIGHT = 10000;
|
24
26
|
|
25
27
|
// Used to trigger the execution of Collectors::ThreadState, which implements all of the sampling logic
|
26
28
|
// itself; this class only implements the "when to do it" part.
|
@@ -96,6 +98,7 @@ struct cpu_and_wall_time_worker_state {
|
|
96
98
|
bool no_signals_workaround_enabled;
|
97
99
|
bool dynamic_sampling_rate_enabled;
|
98
100
|
bool allocation_profiling_enabled;
|
101
|
+
bool allocation_counting_enabled;
|
99
102
|
bool skip_idle_samples_for_testing;
|
100
103
|
VALUE self_instance;
|
101
104
|
VALUE thread_context_collector_instance;
|
@@ -104,7 +107,6 @@ struct cpu_and_wall_time_worker_state {
|
|
104
107
|
dynamic_sampling_rate_state cpu_dynamic_sampling_rate;
|
105
108
|
discrete_dynamic_sampler allocation_sampler;
|
106
109
|
VALUE gc_tracepoint; // Used to get gc start/finish information
|
107
|
-
VALUE object_allocation_tracepoint; // Used to get allocation counts and allocation profiling
|
108
110
|
|
109
111
|
// These are mutable and used to signal things between the worker thread and other threads
|
110
112
|
|
@@ -117,7 +119,7 @@ struct cpu_and_wall_time_worker_state {
|
|
117
119
|
|
118
120
|
// Others
|
119
121
|
|
120
|
-
// Used to detect/avoid nested sampling, e.g. when
|
122
|
+
// Used to detect/avoid nested sampling, e.g. when on_newobj_event gets triggered by a memory allocation
|
121
123
|
// that happens during another sample.
|
122
124
|
bool during_sample;
|
123
125
|
|
@@ -181,6 +183,7 @@ static VALUE _native_initialize(
|
|
181
183
|
VALUE dynamic_sampling_rate_enabled,
|
182
184
|
VALUE dynamic_sampling_rate_overhead_target_percentage,
|
183
185
|
VALUE allocation_profiling_enabled,
|
186
|
+
VALUE allocation_counting_enabled,
|
184
187
|
VALUE skip_idle_samples_for_testing
|
185
188
|
);
|
186
189
|
static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
|
@@ -216,12 +219,28 @@ static void grab_gvl_and_sample(void);
|
|
216
219
|
static void reset_stats_not_thread_safe(struct cpu_and_wall_time_worker_state *state);
|
217
220
|
static void sleep_for(uint64_t time_ns);
|
218
221
|
static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self);
|
219
|
-
static void on_newobj_event(VALUE
|
222
|
+
static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2);
|
220
223
|
static void disable_tracepoints(struct cpu_and_wall_time_worker_state *state);
|
221
224
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
|
222
225
|
static VALUE rescued_sample_allocation(VALUE tracepoint_data);
|
223
226
|
static void delayed_error(struct cpu_and_wall_time_worker_state *state, const char *error);
|
224
227
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
|
228
|
+
static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
|
229
|
+
static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
230
|
+
|
231
|
+
// We're using `on_newobj_event` function with `rb_add_event_hook2`, which requires in its public signature a function
|
232
|
+
// with signature `rb_event_hook_func_t` which doesn't match `on_newobj_event`.
|
233
|
+
//
|
234
|
+
// But in practice, because we pass the `RUBY_EVENT_HOOK_FLAG_RAW_ARG` flag to `rb_add_event_hook2`, it casts the
|
235
|
+
// expected signature into a `rb_event_hook_raw_arg_func_t`:
|
236
|
+
// > typedef void (*rb_event_hook_raw_arg_func_t)(VALUE data, const rb_trace_arg_t *arg); (from vm_trace.c)
|
237
|
+
// which does match `on_newobj_event`.
|
238
|
+
//
|
239
|
+
// So TL;DR we're just doing this here to avoid the warning and explain why the apparent mismatch in function signatures.
|
240
|
+
#pragma GCC diagnostic push
|
241
|
+
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
242
|
+
static const rb_event_hook_func_t on_newobj_event_as_hook = (rb_event_hook_func_t) on_newobj_event;
|
243
|
+
#pragma GCC diagnostic pop
|
225
244
|
|
226
245
|
// Note on sampler global state safety:
|
227
246
|
//
|
@@ -276,7 +295,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
276
295
|
// https://bugs.ruby-lang.org/issues/18007 for a discussion around this.
|
277
296
|
rb_define_alloc_func(collectors_cpu_and_wall_time_worker_class, _native_new);
|
278
297
|
|
279
|
-
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_initialize", _native_initialize,
|
298
|
+
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_initialize", _native_initialize, 10);
|
280
299
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_sampling_loop", _native_sampling_loop, 1);
|
281
300
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stop", _native_stop, 2);
|
282
301
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
|
@@ -285,7 +304,9 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
285
304
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_allocation_count", _native_allocation_count, 0);
|
286
305
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_is_running?", _native_is_running, 1);
|
287
306
|
rb_define_singleton_method(testing_module, "_native_current_sigprof_signal_handler", _native_current_sigprof_signal_handler, 0);
|
288
|
-
|
307
|
+
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_hold_signals", _native_hold_signals, 0);
|
308
|
+
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_resume_signals", _native_resume_signals, 0);
|
309
|
+
// TODO: Remove `_native_is_running` from `testing_module` (should be in class) once `prof-correctness` has been updated to not need it
|
289
310
|
rb_define_singleton_method(testing_module, "_native_is_running?", _native_is_running, 1);
|
290
311
|
rb_define_singleton_method(testing_module, "_native_install_testing_signal_handler", _native_install_testing_signal_handler, 0);
|
291
312
|
rb_define_singleton_method(testing_module, "_native_remove_testing_signal_handler", _native_remove_testing_signal_handler, 0);
|
@@ -312,6 +333,8 @@ static const rb_data_type_t cpu_and_wall_time_worker_typed_data = {
|
|
312
333
|
};
|
313
334
|
|
314
335
|
static VALUE _native_new(VALUE klass) {
|
336
|
+
long now = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
|
337
|
+
|
315
338
|
struct cpu_and_wall_time_worker_state *state = ruby_xcalloc(1, sizeof(struct cpu_and_wall_time_worker_state));
|
316
339
|
|
317
340
|
// Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
|
@@ -321,13 +344,13 @@ static VALUE _native_new(VALUE klass) {
|
|
321
344
|
state->no_signals_workaround_enabled = false;
|
322
345
|
state->dynamic_sampling_rate_enabled = true;
|
323
346
|
state->allocation_profiling_enabled = false;
|
347
|
+
state->allocation_counting_enabled = false;
|
324
348
|
state->skip_idle_samples_for_testing = false;
|
325
349
|
state->thread_context_collector_instance = Qnil;
|
326
350
|
state->idle_sampling_helper_instance = Qnil;
|
327
351
|
state->owner_thread = Qnil;
|
328
352
|
dynamic_sampling_rate_init(&state->cpu_dynamic_sampling_rate);
|
329
353
|
state->gc_tracepoint = Qnil;
|
330
|
-
state->object_allocation_tracepoint = Qnil;
|
331
354
|
|
332
355
|
atomic_init(&state->should_run, false);
|
333
356
|
state->failure_exception = Qnil;
|
@@ -336,15 +359,12 @@ static VALUE _native_new(VALUE klass) {
|
|
336
359
|
state->during_sample = false;
|
337
360
|
|
338
361
|
reset_stats_not_thread_safe(state);
|
339
|
-
|
340
|
-
long now = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
341
|
-
if (now == 0) {
|
342
|
-
ruby_xfree(state);
|
343
|
-
rb_raise(rb_eRuntimeError, ERR_CLOCK_FAIL);
|
344
|
-
}
|
345
|
-
|
346
362
|
discrete_dynamic_sampler_init(&state->allocation_sampler, "allocation", now);
|
347
363
|
|
364
|
+
// Note: As of this writing, no new Ruby objects get created and stored in the state. If that ever changes, remember
|
365
|
+
// to keep them on the stack and mark them with RB_GC_GUARD -- otherwise it's possible for a GC to run and
|
366
|
+
// since the instance representing the state does not yet exist, such objects will not get marked.
|
367
|
+
|
348
368
|
return state->self_instance = TypedData_Wrap_Struct(klass, &cpu_and_wall_time_worker_typed_data, state);
|
349
369
|
}
|
350
370
|
|
@@ -358,6 +378,7 @@ static VALUE _native_initialize(
|
|
358
378
|
VALUE dynamic_sampling_rate_enabled,
|
359
379
|
VALUE dynamic_sampling_rate_overhead_target_percentage,
|
360
380
|
VALUE allocation_profiling_enabled,
|
381
|
+
VALUE allocation_counting_enabled,
|
361
382
|
VALUE skip_idle_samples_for_testing
|
362
383
|
) {
|
363
384
|
ENFORCE_BOOLEAN(gc_profiling_enabled);
|
@@ -365,6 +386,7 @@ static VALUE _native_initialize(
|
|
365
386
|
ENFORCE_BOOLEAN(dynamic_sampling_rate_enabled);
|
366
387
|
ENFORCE_TYPE(dynamic_sampling_rate_overhead_target_percentage, T_FLOAT);
|
367
388
|
ENFORCE_BOOLEAN(allocation_profiling_enabled);
|
389
|
+
ENFORCE_BOOLEAN(allocation_counting_enabled);
|
368
390
|
ENFORCE_BOOLEAN(skip_idle_samples_for_testing)
|
369
391
|
|
370
392
|
struct cpu_and_wall_time_worker_state *state;
|
@@ -374,6 +396,7 @@ static VALUE _native_initialize(
|
|
374
396
|
state->no_signals_workaround_enabled = (no_signals_workaround_enabled == Qtrue);
|
375
397
|
state->dynamic_sampling_rate_enabled = (dynamic_sampling_rate_enabled == Qtrue);
|
376
398
|
state->allocation_profiling_enabled = (allocation_profiling_enabled == Qtrue);
|
399
|
+
state->allocation_counting_enabled = (allocation_counting_enabled == Qtrue);
|
377
400
|
state->skip_idle_samples_for_testing = (skip_idle_samples_for_testing == Qtrue);
|
378
401
|
|
379
402
|
double total_overhead_target_percentage = NUM2DBL(dynamic_sampling_rate_overhead_target_percentage);
|
@@ -390,7 +413,6 @@ static VALUE _native_initialize(
|
|
390
413
|
state->thread_context_collector_instance = enforce_thread_context_collector_instance(thread_context_collector_instance);
|
391
414
|
state->idle_sampling_helper_instance = idle_sampling_helper_instance;
|
392
415
|
state->gc_tracepoint = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_GC_ENTER | RUBY_INTERNAL_EVENT_GC_EXIT, on_gc_event, NULL /* unused */);
|
393
|
-
state->object_allocation_tracepoint = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, on_newobj_event, NULL /* unused */);
|
394
416
|
|
395
417
|
return Qtrue;
|
396
418
|
}
|
@@ -405,7 +427,6 @@ static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr) {
|
|
405
427
|
rb_gc_mark(state->failure_exception);
|
406
428
|
rb_gc_mark(state->stop_thread);
|
407
429
|
rb_gc_mark(state->gc_tracepoint);
|
408
|
-
rb_gc_mark(state->object_allocation_tracepoint);
|
409
430
|
}
|
410
431
|
|
411
432
|
// Called in a background thread created in CpuAndWallTimeWorker#start
|
@@ -751,7 +772,14 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
751
772
|
// because they may raise exceptions.
|
752
773
|
install_sigprof_signal_handler(handle_sampling_signal, "handle_sampling_signal");
|
753
774
|
if (state->gc_profiling_enabled) rb_tracepoint_enable(state->gc_tracepoint);
|
754
|
-
if (state->allocation_profiling_enabled)
|
775
|
+
if (state->allocation_profiling_enabled) {
|
776
|
+
rb_add_event_hook2(
|
777
|
+
on_newobj_event_as_hook,
|
778
|
+
RUBY_INTERNAL_EVENT_NEWOBJ,
|
779
|
+
state->self_instance,
|
780
|
+
RUBY_EVENT_HOOK_FLAG_SAFE | RUBY_EVENT_HOOK_FLAG_RAW_ARG)
|
781
|
+
;
|
782
|
+
}
|
755
783
|
|
756
784
|
// Flag the profiler as running before we release the GVL, in case anyone's waiting to know about it
|
757
785
|
rb_funcall(instance, rb_intern("signal_running"), 0);
|
@@ -1032,46 +1060,87 @@ static void sleep_for(uint64_t time_ns) {
|
|
1032
1060
|
}
|
1033
1061
|
|
1034
1062
|
static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
|
1035
|
-
|
1063
|
+
struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
|
1064
|
+
|
1065
|
+
bool are_allocations_being_tracked = state != NULL && state->allocation_profiling_enabled && state->allocation_counting_enabled;
|
1036
1066
|
|
1037
1067
|
return are_allocations_being_tracked ? ULL2NUM(allocation_count) : Qnil;
|
1038
1068
|
}
|
1039
1069
|
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
}
|
1070
|
+
#define HANDLE_CLOCK_FAILURE(call) ({ \
|
1071
|
+
long _result = (call); \
|
1072
|
+
if (_result == 0) { \
|
1073
|
+
delayed_error(state, ERR_CLOCK_FAIL); \
|
1074
|
+
return; \
|
1075
|
+
} \
|
1076
|
+
_result; \
|
1077
|
+
})
|
1049
1078
|
|
1079
|
+
// Implements memory-related profiling events. This function is called by Ruby via the `rb_add_event_hook2`
|
1080
|
+
// when the RUBY_INTERNAL_EVENT_NEWOBJ event is triggered.
|
1081
|
+
//
|
1082
|
+
// When allocation sampling is enabled, this function gets called for almost all* objects allocated by the Ruby VM.
|
1083
|
+
// (*In some weird cases the VM may skip this tracepoint.)
|
1084
|
+
//
|
1085
|
+
// At a high level, there's two paths through this function:
|
1086
|
+
// 1. should_sample == false -> return
|
1087
|
+
// 2. should_sample == true -> sample
|
1088
|
+
//
|
1089
|
+
// On big applications, path 1. is the hottest, since we don't sample every object. So it's quite important for it to
|
1090
|
+
// be as fast as possible.
|
1091
|
+
//
|
1092
|
+
// NOTE: You may be wondering why we don't use any of the arguments to this function. It turns out it's possible to just
|
1093
|
+
// call `rb_tracearg_from_tracepoint(anything)` anywhere during this function or its callees to get the data, so that's
|
1094
|
+
// why it's not being passed as an argument.
|
1095
|
+
static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2) {
|
1050
1096
|
struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
1051
1097
|
|
1052
1098
|
// This should not happen in a normal situation because the tracepoint is always enabled after the instance is set
|
1053
1099
|
// and disabled before it is cleared, but just in case...
|
1054
1100
|
if (state == NULL) return;
|
1055
1101
|
|
1056
|
-
|
1102
|
+
if (RB_UNLIKELY(state->allocation_counting_enabled)) {
|
1103
|
+
// Update thread-local allocation count
|
1104
|
+
if (RB_UNLIKELY(allocation_count == UINT64_MAX)) {
|
1105
|
+
allocation_count = 0;
|
1106
|
+
} else {
|
1107
|
+
allocation_count++;
|
1108
|
+
}
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
// In rare cases, we may actually be allocating an object as part of profiler sampling. We don't want to recursively
|
1057
1112
|
// sample, so we just return early
|
1058
1113
|
if (state->during_sample) {
|
1059
1114
|
state->stats.allocations_during_sample++;
|
1060
1115
|
return;
|
1061
1116
|
}
|
1062
1117
|
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1118
|
+
// Hot path: Dynamic sampling rate is usually enabled and the sampling decision is usually false
|
1119
|
+
if (RB_LIKELY(state->dynamic_sampling_rate_enabled && !discrete_dynamic_sampler_should_sample(&state->allocation_sampler))) {
|
1120
|
+
state->stats.allocation_skipped++;
|
1121
|
+
|
1122
|
+
coarse_instant now = monotonic_coarse_wall_time_now_ns();
|
1123
|
+
HANDLE_CLOCK_FAILURE(now.timestamp_ns);
|
1124
|
+
|
1125
|
+
bool needs_readjust = discrete_dynamic_sampler_skipped_sample(&state->allocation_sampler, now);
|
1126
|
+
if (RB_UNLIKELY(needs_readjust)) {
|
1127
|
+
// We rarely readjust, so this is a cold path
|
1128
|
+
// Also, while above we used the cheaper monotonic_coarse, for this call we want the regular monotonic call,
|
1129
|
+
// which is why we end up getting time "again".
|
1130
|
+
discrete_dynamic_sampler_readjust(
|
1131
|
+
&state->allocation_sampler, HANDLE_CLOCK_FAILURE(monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE))
|
1132
|
+
);
|
1072
1133
|
}
|
1134
|
+
|
1135
|
+
return;
|
1073
1136
|
}
|
1074
1137
|
|
1138
|
+
// From here on, we've decided to go ahead with the sample, which is way less common than skipping it
|
1139
|
+
|
1140
|
+
discrete_dynamic_sampler_before_sample(
|
1141
|
+
&state->allocation_sampler, HANDLE_CLOCK_FAILURE(monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE))
|
1142
|
+
);
|
1143
|
+
|
1075
1144
|
// @ivoanjo: Strictly speaking, this is not needed because Ruby should not call the same tracepoint while a previous
|
1076
1145
|
// invocation is still pending, (e.g. it wouldn't call `on_newobj_event` while it's already running), but I decided
|
1077
1146
|
// to keep this here for consistency -- every call to the thread context (other than the special gc calls which are
|
@@ -1079,7 +1148,7 @@ static void on_newobj_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused)
|
|
1079
1148
|
state->during_sample = true;
|
1080
1149
|
|
1081
1150
|
// Rescue against any exceptions that happen during sampling
|
1082
|
-
safely_call(rescued_sample_allocation,
|
1151
|
+
safely_call(rescued_sample_allocation, Qnil, state->self_instance);
|
1083
1152
|
|
1084
1153
|
if (state->dynamic_sampling_rate_enabled) {
|
1085
1154
|
long now = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
@@ -1104,9 +1173,7 @@ static void disable_tracepoints(struct cpu_and_wall_time_worker_state *state) {
|
|
1104
1173
|
if (state->gc_tracepoint != Qnil) {
|
1105
1174
|
rb_tracepoint_disable(state->gc_tracepoint);
|
1106
1175
|
}
|
1107
|
-
|
1108
|
-
rb_tracepoint_disable(state->object_allocation_tracepoint);
|
1109
|
-
}
|
1176
|
+
rb_remove_event_hook_with_data(on_newobj_event_as_hook, state->self_instance);
|
1110
1177
|
}
|
1111
1178
|
|
1112
1179
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self) {
|
@@ -1122,13 +1189,14 @@ static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self) {
|
|
1122
1189
|
}
|
1123
1190
|
}
|
1124
1191
|
|
1125
|
-
static VALUE rescued_sample_allocation(VALUE
|
1192
|
+
static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
|
1126
1193
|
struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
1127
1194
|
|
1128
1195
|
// This should not happen in a normal situation because on_newobj_event already checked for this, but just in case...
|
1129
1196
|
if (state == NULL) return Qnil;
|
1130
1197
|
|
1131
|
-
|
1198
|
+
// If we're getting called from inside a tracepoint/event hook, Ruby exposes the data using this function.
|
1199
|
+
rb_trace_arg_t *data = rb_tracearg_from_tracepoint(Qnil);
|
1132
1200
|
VALUE new_object = rb_tracearg_object(data);
|
1133
1201
|
|
1134
1202
|
unsigned long allocations_since_last_sample = state->dynamic_sampling_rate_enabled ?
|
@@ -1136,9 +1204,15 @@ static VALUE rescued_sample_allocation(VALUE tracepoint_data) {
|
|
1136
1204
|
discrete_dynamic_sampler_events_since_last_sample(&state->allocation_sampler) :
|
1137
1205
|
// if we aren't, then we're sampling every event
|
1138
1206
|
1;
|
1139
|
-
|
1207
|
+
|
1208
|
+
// To control bias from sampling, we clamp the maximum weight attributed to a single allocation sample. This avoids
|
1209
|
+
// assigning a very large number to a sample, if for instance the dynamic sampling mechanism chose a really big interval.
|
1140
1210
|
unsigned int weight = allocations_since_last_sample > MAX_ALLOC_WEIGHT ? MAX_ALLOC_WEIGHT : (unsigned int) allocations_since_last_sample;
|
1141
1211
|
thread_context_collector_sample_allocation(state->thread_context_collector_instance, weight, new_object);
|
1212
|
+
// ...but we still represent the skipped samples in the profile, thus the data will account for all allocations.
|
1213
|
+
if (weight < allocations_since_last_sample) {
|
1214
|
+
thread_context_collector_sample_skipped_allocation_samples(state->thread_context_collector_instance, allocations_since_last_sample - weight);
|
1215
|
+
}
|
1142
1216
|
|
1143
1217
|
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
1144
1218
|
return Qnil;
|
@@ -1159,3 +1233,17 @@ static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VA
|
|
1159
1233
|
|
1160
1234
|
return Qnil;
|
1161
1235
|
}
|
1236
|
+
|
1237
|
+
// Masks SIGPROF interruptions for the current thread. Please don't use this -- you may end up with incomplete
|
1238
|
+
// profiling data.
|
1239
|
+
static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self) {
|
1240
|
+
block_sigprof_signal_handler_from_running_in_current_thread();
|
1241
|
+
return Qtrue;
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
// Unmasks SIGPROF interruptions for the current thread. If there's a pending sample, it'll be triggered inside this
|
1245
|
+
// method.
|
1246
|
+
static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
1247
|
+
unblock_sigprof_signal_handler_from_running_in_current_thread();
|
1248
|
+
return Qtrue;
|
1249
|
+
}
|