datadog 2.46.0 → 2.48.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 +56 -2
- data/LICENSE-3rdparty.csv +1 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +143 -86
- data/ext/datadog_profiling_native_extension/collectors_stack.h +9 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +6 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -13
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +67 -14
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +8 -1
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/libdatadog_api/extconf.rb +9 -7
- data/ext/libdatadog_api/trace_exporter.c +34 -7
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/ai_guard/component.rb +1 -1
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +1 -9
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +3 -3
- data/lib/datadog/ai_guard/evaluation/client.rb +3 -3
- data/lib/datadog/ai_guard/evaluation.rb +2 -2
- data/lib/datadog/ai_guard/http_client.rb +3 -2
- data/lib/datadog/ai_guard/redaction.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +3 -3
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +5366 -1517
- data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -2
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +1 -1
- data/lib/datadog/appsec/compressed_json.rb +1 -1
- data/lib/datadog/appsec/configuration.rb +3 -3
- data/lib/datadog/appsec/context.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +11 -1
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +12 -4
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +7 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -5
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +31 -4
- data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +8 -7
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -5
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +8 -7
- data/lib/datadog/appsec/metrics/collector.rb +5 -5
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +3 -3
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +1 -1
- data/lib/datadog/appsec/response.rb +1 -1
- data/lib/datadog/appsec/security_engine/engine.rb +8 -7
- data/lib/datadog/appsec/security_engine/runner.rb +2 -2
- data/lib/datadog/appsec/trace_keeper.rb +1 -1
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +14 -13
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +12 -11
- data/lib/datadog/core/configuration/components_state.rb +8 -1
- data/lib/datadog/core/configuration/settings.rb +5 -2
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
- data/lib/datadog/core/configuration.rb +2 -2
- data/lib/datadog/core/crashtracking/component.rb +1 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/environment/cgroup.rb +2 -2
- data/lib/datadog/core/environment/container.rb +3 -3
- data/lib/datadog/core/metrics/client.rb +6 -6
- data/lib/datadog/core/process_discovery.rb +1 -1
- data/lib/datadog/core/remote/client.rb +44 -3
- data/lib/datadog/core/remote/dispatcher.rb +34 -3
- data/lib/datadog/core/remote/tie/tracing.rb +4 -3
- data/lib/datadog/core/remote/transport/http.rb +2 -2
- data/lib/datadog/core/runtime/metrics.rb +14 -14
- data/lib/datadog/core/semaphore.rb +3 -1
- data/lib/datadog/core/telemetry/event/app_started.rb +9 -9
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/logging.rb +1 -1
- data/lib/datadog/core/telemetry/request.rb +9 -3
- data/lib/datadog/core/telemetry/transport/http.rb +2 -2
- data/lib/datadog/core/telemetry/worker.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/net.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
- data/lib/datadog/core/transport/http/builder.rb +1 -1
- data/lib/datadog/core/transport/http.rb +3 -3
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +48 -27
- data/lib/datadog/data_streams/transport/http.rb +1 -1
- data/lib/datadog/data_streams.rb +16 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +48 -11
- data/lib/datadog/di/component.rb +73 -2
- data/lib/datadog/di/configuration.rb +19 -0
- data/lib/datadog/di/contrib/active_record.rb +1 -1
- data/lib/datadog/di/el/compiler.rb +4 -4
- data/lib/datadog/di/el/evaluator.rb +247 -43
- data/lib/datadog/di/el/expression.rb +36 -6
- data/lib/datadog/di/error.rb +16 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +3 -2
- data/lib/datadog/di/instrumenter.rb +39 -10
- data/lib/datadog/di/probe_notification_builder.rb +58 -10
- data/lib/datadog/di/probe_notifier_worker.rb +1 -1
- data/lib/datadog/di/remote.rb +46 -2
- data/lib/datadog/di/serializer.rb +47 -13
- data/lib/datadog/di.rb +27 -0
- data/lib/datadog/error_tracking/component.rb +1 -1
- data/lib/datadog/error_tracking/configuration.rb +1 -1
- data/lib/datadog/kit/appsec/events/v2.rb +6 -6
- data/lib/datadog/kit/appsec/events.rb +1 -1
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/kit/identity.rb +1 -1
- data/lib/datadog/open_feature/activation.rb +26 -1
- data/lib/datadog/open_feature/agentless/configuration_source.rb +94 -15
- data/lib/datadog/open_feature/component.rb +22 -2
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +6 -0
- data/lib/datadog/open_feature/configuration.rb +10 -4
- data/lib/datadog/open_feature/evaluation_engine.rb +62 -4
- data/lib/datadog/open_feature/exposures/buffer.rb +4 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +17 -4
- data/lib/datadog/open_feature/exposures/worker.rb +37 -6
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +5 -5
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +1 -1
- data/lib/datadog/open_feature/hooks/debug_logging_hook.rb +56 -0
- data/lib/datadog/open_feature/hooks/evaluation_telemetry_opt_out_hook.rb +25 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +2 -2
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +1 -1
- data/lib/datadog/open_feature/native_evaluator.rb +1 -1
- data/lib/datadog/open_feature/noop_evaluator.rb +1 -1
- data/lib/datadog/open_feature/provider.rb +69 -12
- data/lib/datadog/open_feature/remote.rb +8 -1
- data/lib/datadog/open_feature/resolution_details.rb +2 -2
- data/lib/datadog/open_feature/transport.rb +6 -6
- data/lib/datadog/opentelemetry/api/context.rb +3 -3
- data/lib/datadog/opentelemetry/logs.rb +5 -5
- data/lib/datadog/opentelemetry/metrics.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +2 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +3 -3
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -4
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +37 -6
- data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
- data/lib/datadog/profiling/component.rb +41 -39
- data/lib/datadog/profiling/exporter.rb +4 -6
- data/lib/datadog/profiling/http_transport.rb +3 -3
- data/lib/datadog/profiling/profiler.rb +2 -2
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/tag_builder.rb +1 -1
- data/lib/datadog/symbol_database/extractor.rb +8 -8
- data/lib/datadog/symbol_database/uploader.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/client_ip.rb +1 -1
- data/lib/datadog/tracing/component.rb +15 -10
- data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
- data/lib/datadog/tracing/configuration/ext.rb +2 -0
- data/lib/datadog/tracing/configuration/settings.rb +14 -3
- data/lib/datadog/tracing/context.rb +1 -1
- data/lib/datadog/tracing/context_provider.rb +8 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/data_streams.rb +27 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -2
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +17 -12
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +16 -9
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +14 -8
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -4
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/plugin.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -1
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +21 -6
- data/lib/datadog/tracing/contrib/http.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +14 -8
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +14 -8
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/framework.rb +7 -7
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +4 -4
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +17 -10
- data/lib/datadog/tracing/contrib/sequel/database.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_env_parser.rb +1 -1
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +102 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/waterdrop.rb +1 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -3
- data/lib/datadog/tracing/distributed/datadog.rb +3 -3
- data/lib/datadog/tracing/distributed/propagation.rb +7 -7
- data/lib/datadog/tracing/distributed/trace_context.rb +1 -1
- data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +1 -1
- data/lib/datadog/tracing/otel_thread_context.rb +3 -3
- data/lib/datadog/tracing/pipeline.rb +1 -1
- data/lib/datadog/tracing/remote.rb +50 -19
- data/lib/datadog/tracing/sampling/priority_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/trace_digest.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +6 -6
- data/lib/datadog/tracing/tracer.rb +6 -6
- data/lib/datadog/tracing/transport/http/telemetry.rb +1 -1
- data/lib/datadog/tracing/transport/http.rb +2 -2
- data/lib/datadog/tracing/transport/io.rb +1 -1
- data/lib/datadog/tracing/transport/native.rb +3 -3
- data/lib/datadog/tracing/transport/statistics.rb +2 -2
- data/lib/datadog/tracing/transport/telemetry.rb +3 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +12 -12
- data/lib/datadog/tracing/transport/traces.rb +1 -1
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +9 -8
- data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ac4a0fce689b8c65bbe4c00847dbaf3e84bf7eda13ea48fc40cab57d5332a04f
|
|
4
|
+
data.tar.gz: dbf9526b321135b7e9e014578a5abe92a89e339a4ba2d9f7997718194e76a302
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dbbbc2ca84a95852a6614ba6cbc21c0fc68c4badef35c34dc29059ef6feffb0307ac0d19ffc955d8b7ac3f807007d4ea9577490dee99e0bb9f98f4d158ac8093
|
|
7
|
+
data.tar.gz: 3ec630b843cd8e57b14a227afe815c1e07f8a5c5bcbbffd62a41a19c57c5f204e8302059dd9bce0c7d89d1667f7a93ae6219686ec55aef5961ee23082ff56f26
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.48.0] - 2026-11-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* Dynamic Instrumentation: Limit condition, capture-expression, and template evaluation CPU time with `DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS` (default `50`); over-budget evaluation is reported as an evaluation error. ([#6223][])
|
|
10
|
+
* Open Feature: Add onboarding diagnostics for configuration delivery, provider readiness, flag evaluations, and exposures with `DD_TRACE_DEBUG=true`. Evaluation logs include raw data that may contain personal or sensitive information. ([#6519][])
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
* Core: Require C11 (`-std=gnu11`) support to build native extensions on Linux. ([#6596][])
|
|
15
|
+
* Profiling: Show class and module names in profiler stack frames by default, e.g. `Foo::Bar#baz` instead of `baz`, making methods easier to identify. ([#6537][])
|
|
16
|
+
* Dynamic Instrumentation: Lower the per-call limit of the `matches` expression operator from 500 ms to 50 ms of wall time; a slow regular expression in a probe now delays the instrumented method by at most 50 ms per call and reports an evaluation error. ([#6223][])
|
|
17
|
+
* Data Streams: Start a new pathway when a consume and the produce that follows it run on different threads; to keep one pathway across the hand-off, pass the context with `set_produce_checkpoint` and `set_consume_checkpoint`. ([#6532][])
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
* Tracing: Fix the `_dd.rc.client_id` span tag occasionally carrying the client id of a different remote-configuration connection during component reconnection. ([#6601][])
|
|
22
|
+
* AppSec: Fix missing SQL injection detection in applications using `ActiveRecord` 8.0 and later. ([#6581][])
|
|
23
|
+
* AI Guard: Fix a rare crash when building the AI Guard client endpoint while the Datadog site setting changes concurrently. ([#6601][])
|
|
24
|
+
* Data Streams: Fix full-pathway latency inflated by minutes, and messages linked to the wrong pathway, in multi-threaded or forking apps such as `Karafka` consumers and `ActiveJob` workers. ([#6532][])
|
|
25
|
+
|
|
26
|
+
## [2.47.0] - 2026-10-26
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
* Tracing: Add quantized request paths to outbound HTTP client resource names, such as `GET /users/*`; enable with `DD_TRACE_HTTP_CLIENT_RESOURCE_NAME_QUANTIZE=true`. ([#6298][])
|
|
31
|
+
* Open Feature: Let evaluations opt out of flag evaluation events, metrics, and span tags with `dd_evaluation_telemetry_opt_out: true` in the evaluation context; enable it with `DD_FEATURE_FLAGS_EVALUATION_TELEMETRY_PER_SUBJECT_OPT_OUT_ENABLED=true`. ([#6486][])
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
* AppSec: Update `libddwaf` to 1.30.0.1.0. ([#6548][])
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
* Core: Fix forked processes, such as Puma and Unicorn workers, reporting no runtime metrics when the parent process traced before forking. ([#6500][]) ([@dduugg][])
|
|
40
|
+
* Profiling: Fix the "no signals" workaround being enabled when `mysql2` uses MariaDB Connector/C 3.x. ([#6543][])
|
|
41
|
+
* AppSec: Fix ruleset updates with Remote Configuration. ([#6547][])
|
|
42
|
+
* AppSec: Fix duplicate JSON serialization of Rails and Sinatra response objects when application security is enabled. ([#6548][])
|
|
43
|
+
|
|
5
44
|
## [2.46.0] - 2026-10-19
|
|
6
45
|
|
|
7
46
|
### Added
|
|
@@ -3851,7 +3890,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3851
3890
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3852
3891
|
|
|
3853
3892
|
|
|
3854
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3893
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.48.0...master
|
|
3894
|
+
[2.48.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.47.0...v2.48.0
|
|
3895
|
+
[2.47.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.46.0...v2.47.0
|
|
3855
3896
|
[2.46.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.45.0...v2.46.0
|
|
3856
3897
|
[2.45.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.44.0...v2.45.0
|
|
3857
3898
|
[2.44.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.43.0...v2.44.0
|
|
@@ -5687,6 +5728,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5687
5728
|
[#6213]: https://github.com/DataDog/dd-trace-rb/issues/6213
|
|
5688
5729
|
[#6219]: https://github.com/DataDog/dd-trace-rb/issues/6219
|
|
5689
5730
|
[#6220]: https://github.com/DataDog/dd-trace-rb/issues/6220
|
|
5731
|
+
[#6223]: https://github.com/DataDog/dd-trace-rb/issues/6223
|
|
5690
5732
|
[#6232]: https://github.com/DataDog/dd-trace-rb/issues/6232
|
|
5691
5733
|
[#6234]: https://github.com/DataDog/dd-trace-rb/issues/6234
|
|
5692
5734
|
[#6242]: https://github.com/DataDog/dd-trace-rb/issues/6242
|
|
@@ -5694,6 +5736,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5694
5736
|
[#6261]: https://github.com/DataDog/dd-trace-rb/issues/6261
|
|
5695
5737
|
[#6286]: https://github.com/DataDog/dd-trace-rb/issues/6286
|
|
5696
5738
|
[#6291]: https://github.com/DataDog/dd-trace-rb/issues/6291
|
|
5739
|
+
[#6298]: https://github.com/DataDog/dd-trace-rb/issues/6298
|
|
5697
5740
|
[#6316]: https://github.com/DataDog/dd-trace-rb/issues/6316
|
|
5698
5741
|
[#6320]: https://github.com/DataDog/dd-trace-rb/issues/6320
|
|
5699
5742
|
[#6339]: https://github.com/DataDog/dd-trace-rb/issues/6339
|
|
@@ -5721,7 +5764,18 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5721
5764
|
[#6474]: https://github.com/DataDog/dd-trace-rb/issues/6474
|
|
5722
5765
|
[#6481]: https://github.com/DataDog/dd-trace-rb/issues/6481
|
|
5723
5766
|
[#6485]: https://github.com/DataDog/dd-trace-rb/issues/6485
|
|
5767
|
+
[#6486]: https://github.com/DataDog/dd-trace-rb/issues/6486
|
|
5724
5768
|
[#6488]: https://github.com/DataDog/dd-trace-rb/issues/6488
|
|
5769
|
+
[#6500]: https://github.com/DataDog/dd-trace-rb/issues/6500
|
|
5770
|
+
[#6519]: https://github.com/DataDog/dd-trace-rb/issues/6519
|
|
5771
|
+
[#6532]: https://github.com/DataDog/dd-trace-rb/issues/6532
|
|
5772
|
+
[#6537]: https://github.com/DataDog/dd-trace-rb/issues/6537
|
|
5773
|
+
[#6543]: https://github.com/DataDog/dd-trace-rb/issues/6543
|
|
5774
|
+
[#6547]: https://github.com/DataDog/dd-trace-rb/issues/6547
|
|
5775
|
+
[#6548]: https://github.com/DataDog/dd-trace-rb/issues/6548
|
|
5776
|
+
[#6581]: https://github.com/DataDog/dd-trace-rb/issues/6581
|
|
5777
|
+
[#6596]: https://github.com/DataDog/dd-trace-rb/issues/6596
|
|
5778
|
+
[#6601]: https://github.com/DataDog/dd-trace-rb/issues/6601
|
|
5725
5779
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5726
5780
|
[@Azure7111]: https://github.com/Azure7111
|
|
5727
5781
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -5878,4 +5932,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5878
5932
|
[@y-yagi]: https://github.com/y-yagi
|
|
5879
5933
|
[@yujideveloper]: https://github.com/yujideveloper
|
|
5880
5934
|
[@yukimurasawa]: https://github.com/yukimurasawa
|
|
5881
|
-
[@zachmccormick]: https://github.com/zachmccormick
|
|
5935
|
+
[@zachmccormick]: https://github.com/zachmccormick
|
data/LICENSE-3rdparty.csv
CHANGED
|
@@ -5,3 +5,4 @@
|
|
|
5
5
|
"lib/datadog/tracing/contrib/active_record/vendor","https://github.com/rails/rails/","MIT","Copyright (c) 2005-2018 David Heinemeier Hansson"
|
|
6
6
|
"lib/datadog/tracing/contrib/utils/quantization/http.rb","https://github.com/ruby/uri","BSD-2-Clause","Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved."
|
|
7
7
|
"msgpack","https://rubygems.org/gems/msgpack","Apache-2.0","Copyright (c) 2008-2015 Sadayuki Furuhashi"
|
|
8
|
+
"rubocop/custom_cops/trailing_comma_in_arguments_cop.rb","https://github.com/rubocop/rubocop","MIT","Copyright (c) 2012-25 Bozhidar Batsov"
|
|
@@ -41,7 +41,7 @@ static const char *get_or_compute_native_filename(void *function, st_table *nati
|
|
|
41
41
|
static void initialize_static_ruby_actual_filename(VALUE profiling_module);
|
|
42
42
|
static void add_truncated_frames_placeholder(ddog_prof_Location *locations);
|
|
43
43
|
static void record_placeholder_stack_in_native_code(VALUE recorder_instance, sample_values values, sample_labels labels);
|
|
44
|
-
static void maybe_trim_template_random_ids(ddog_CharSlice *
|
|
44
|
+
static void maybe_trim_template_random_ids(ddog_CharSlice *frame_name, ddog_CharSlice filename, bool frame_name_in_scratch_buffer);
|
|
45
45
|
|
|
46
46
|
// NULL if we weren't able to get the native filename for the Ruby VM.
|
|
47
47
|
// On a static Ruby without libruby.so, `get_or_compute_native_filename` returns `ruby_native_filename` but
|
|
@@ -180,7 +180,7 @@ static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
|
|
|
180
180
|
sample_locations locations;
|
|
181
181
|
sample_locations_initialize(&locations, max_frames_requested, show_classes == Qtrue);
|
|
182
182
|
sampling_buffer buffer;
|
|
183
|
-
sampling_buffer_initialize(&buffer, max_frames_requested);
|
|
183
|
+
sampling_buffer_initialize(&buffer, max_frames_requested, show_classes == Qtrue);
|
|
184
184
|
|
|
185
185
|
ddog_prof_Slice_Label slice_labels = {.ptr = labels, .len = labels_count};
|
|
186
186
|
|
|
@@ -239,6 +239,83 @@ static VALUE native_sample_ensure(VALUE args) {
|
|
|
239
239
|
|
|
240
240
|
#define CHARSLICE_EQUALS(must_be_a_literal, charslice) (strlen("" must_be_a_literal) == charslice.len && strncmp(must_be_a_literal, charslice.ptr, charslice.len) == 0)
|
|
241
241
|
|
|
242
|
+
// The method name on its own, without any class/module name
|
|
243
|
+
static inline ddog_CharSlice unqualified_name(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq) {
|
|
244
|
+
VALUE name = ddtrace_location_base_label(cme, iseq);
|
|
245
|
+
return (name == Qfalse) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// When there's only wall-time in a sample, this means that the thread was not active in the sampled period, so we try
|
|
249
|
+
// to tell what it was doing instead.
|
|
250
|
+
//
|
|
251
|
+
// TODO: `method` is the unqualified method name
|
|
252
|
+
// because we don't always use qualified method names yet,
|
|
253
|
+
// and the checks below need something stable to compare to until we always do.
|
|
254
|
+
static void categorize_sample_state(
|
|
255
|
+
sample_labels labels,
|
|
256
|
+
frame_info frame,
|
|
257
|
+
ddog_CharSlice method,
|
|
258
|
+
DDTRACE_UNUSED ddog_CharSlice filename
|
|
259
|
+
) {
|
|
260
|
+
ddog_prof_Label *state_label = labels.state_label;
|
|
261
|
+
|
|
262
|
+
// Did the caller already provide the state?
|
|
263
|
+
if (labels.is_gvl_waiting_state) {
|
|
264
|
+
state_label->str = DDOG_CHARSLICE_C("waiting for gvl");
|
|
265
|
+
|
|
266
|
+
// Otherwise, we try to categorize what the thread was doing based on what we observe at the top of the stack. This is a very rough
|
|
267
|
+
// approximation, and in the future we hope to replace this with a more accurate approach (such as using the
|
|
268
|
+
// GVL instrumentation API.)
|
|
269
|
+
} else if (!frame.is_ruby_frame) {
|
|
270
|
+
// We know that known versions of Ruby implement these using native code; thus if we find a method with the
|
|
271
|
+
// same name that is not native code, we ignore it, as it's probably a user method that coincidentally
|
|
272
|
+
// has the same name. Thus, even though "matching just by method name" is kinda weak,
|
|
273
|
+
// "matching by method name" + is native code seems actually to be good enough for a lot of cases.
|
|
274
|
+
|
|
275
|
+
if (CHARSLICE_EQUALS("sleep", method)) { // Expected to be Kernel.sleep
|
|
276
|
+
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
277
|
+
} else if (CHARSLICE_EQUALS("select", method)) { // Expected to be Kernel.select
|
|
278
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
279
|
+
} else if (
|
|
280
|
+
CHARSLICE_EQUALS("synchronize", method) || // Expected to be Monitor/Mutex#synchronize on Ruby 2 & 3, and Monitor#synchronize on 4 (Mutex becomes <internal:thread_sync>)
|
|
281
|
+
#ifdef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby < 4
|
|
282
|
+
CHARSLICE_EQUALS("lock", method) || // Expected to be Mutex#lock
|
|
283
|
+
#endif
|
|
284
|
+
CHARSLICE_EQUALS("join", method) // Expected to be Thread#join
|
|
285
|
+
) {
|
|
286
|
+
state_label->str = DDOG_CHARSLICE_C("blocked");
|
|
287
|
+
} else if (CHARSLICE_EQUALS("wait_readable", method)) { // Expected to be IO#wait_readable
|
|
288
|
+
state_label->str = DDOG_CHARSLICE_C("network");
|
|
289
|
+
} else if (CHARSLICE_EQUALS("_native_idle_sampling_loop", method)) { // Expected to be Datadog::Profiler::Collectors::IdleSamplingHelper#_native_idle_sampling_loop
|
|
290
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
291
|
+
} else if (CHARSLICE_EQUALS("_native_sampling_loop", method)) { // Expected to be Datadog::Profiler::Collectors::CpuAndWallTimeWorker#_native_sampling_loop
|
|
292
|
+
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
293
|
+
}
|
|
294
|
+
#ifdef NO_PRIMITIVE_POP // Ruby < 3.2
|
|
295
|
+
else if (CHARSLICE_EQUALS("pop", method)) { // Expected to be Queue/SizedQueue#pop
|
|
296
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
297
|
+
}
|
|
298
|
+
#endif
|
|
299
|
+
} else {
|
|
300
|
+
#ifndef NO_PRIMITIVE_POP // Ruby >= 3.2
|
|
301
|
+
if (CHARSLICE_EQUALS("<internal:thread_sync>", filename)) {
|
|
302
|
+
if (CHARSLICE_EQUALS("pop", method)) { // Expected to be Queue/SizedQueue#pop
|
|
303
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
304
|
+
}
|
|
305
|
+
#ifndef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby >= 4
|
|
306
|
+
else if (CHARSLICE_EQUALS("synchronize", method) || CHARSLICE_EQUALS("lock", method)) { // Expected to be Mutex#lock/synchronize
|
|
307
|
+
state_label->str = DDOG_CHARSLICE_C("blocked");
|
|
308
|
+
} else if (CHARSLICE_EQUALS("sleep", method)) { // Expected to be Mutex#sleep
|
|
309
|
+
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
310
|
+
} else if (CHARSLICE_EQUALS("wait", method)) { // Expected to be ConditionVariable#wait
|
|
311
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
312
|
+
}
|
|
313
|
+
#endif
|
|
314
|
+
}
|
|
315
|
+
#endif
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
242
319
|
// Idea: Should we release the global vm lock (GVL) after we get the data from `rb_profile_frames`? That way other Ruby threads
|
|
243
320
|
// could continue making progress while the sample was ingested into the profile.
|
|
244
321
|
//
|
|
@@ -354,91 +431,45 @@ void sample_thread(
|
|
|
354
431
|
);
|
|
355
432
|
}
|
|
356
433
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
//
|
|
360
|
-
|
|
361
|
-
ddog_CharSlice name_slice = (name == Qfalse) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
|
|
434
|
+
// This frame kept the name we composed for it in an earlier sample, so there's nothing to compose or trim again
|
|
435
|
+
char *cached_name = buffer->cached_names == NULL ? NULL : buffer->cached_names + (i * MAX_CACHED_FRAME_NAME);
|
|
436
|
+
// The length is only ever set together with the name it describes, and frames start out zeroed
|
|
437
|
+
bool name_is_cached = frame.cached_name_len > 0;
|
|
362
438
|
|
|
363
|
-
ddog_CharSlice
|
|
364
|
-
|
|
439
|
+
ddog_CharSlice frame_name;
|
|
440
|
+
// We only keep a name we managed to compose: ddtrace_location_label() also fails when this stack used up the
|
|
441
|
+
// scratch buffer, and keeping the unqualified name it falls back to would stick to the frame even once there's
|
|
442
|
+
// room for it again.
|
|
443
|
+
bool name_is_cacheable = false;
|
|
444
|
+
if (name_is_cached) {
|
|
445
|
+
frame_name = (ddog_CharSlice) {.ptr = cached_name, .len = frame.cached_name_len};
|
|
446
|
+
} else if (show_classes) {
|
|
365
447
|
ssize_t written = ddtrace_location_label(cme, iseq, qualified_name_buf, qualified_name_buf_size);
|
|
366
448
|
if (written > 0) {
|
|
367
|
-
|
|
449
|
+
frame_name = (ddog_CharSlice) {.ptr = qualified_name_buf, .len = written};
|
|
368
450
|
qualified_name_buf += written;
|
|
369
451
|
qualified_name_buf_size -= written;
|
|
452
|
+
name_is_cacheable = true;
|
|
370
453
|
} else {
|
|
371
|
-
|
|
454
|
+
frame_name = unqualified_name(cme, iseq); // just the method name
|
|
372
455
|
}
|
|
456
|
+
} else {
|
|
457
|
+
frame_name = unqualified_name(cme, iseq);
|
|
373
458
|
}
|
|
374
459
|
|
|
375
|
-
// When there's only wall-time in a sample, this means that the thread was not active in the sampled period.
|
|
376
460
|
if (top_of_the_stack && only_wall_time) {
|
|
377
|
-
|
|
378
|
-
if (labels.is_gvl_waiting_state) {
|
|
379
|
-
state_label->str = DDOG_CHARSLICE_C("waiting for gvl");
|
|
380
|
-
|
|
381
|
-
// Otherwise, we try to categorize what the thread was doing based on what we observe at the top of the stack. This is a very rough
|
|
382
|
-
// approximation, and in the future we hope to replace this with a more accurate approach (such as using the
|
|
383
|
-
// GVL instrumentation API.)
|
|
384
|
-
} else if (!frame.is_ruby_frame) {
|
|
385
|
-
// We know that known versions of Ruby implement these using native code; thus if we find a method with the
|
|
386
|
-
// same name that is not native code, we ignore it, as it's probably a user method that coincidentally
|
|
387
|
-
// has the same name. Thus, even though "matching just by method name" is kinda weak,
|
|
388
|
-
// "matching by method name" + is native code seems actually to be good enough for a lot of cases.
|
|
389
|
-
|
|
390
|
-
if (CHARSLICE_EQUALS("sleep", name_slice)) { // Expected to be Kernel.sleep
|
|
391
|
-
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
392
|
-
} else if (CHARSLICE_EQUALS("select", name_slice)) { // Expected to be Kernel.select
|
|
393
|
-
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
394
|
-
} else if (
|
|
395
|
-
CHARSLICE_EQUALS("synchronize", name_slice) || // Expected to be Monitor/Mutex#synchronize on Ruby 2 & 3, and Monitor#synchronize on 4 (Mutex becomes <internal:thread_sync>)
|
|
396
|
-
#ifdef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby < 4
|
|
397
|
-
CHARSLICE_EQUALS("lock", name_slice) || // Expected to be Mutex#lock
|
|
398
|
-
#endif
|
|
399
|
-
CHARSLICE_EQUALS("join", name_slice) // Expected to be Thread#join
|
|
400
|
-
) {
|
|
401
|
-
state_label->str = DDOG_CHARSLICE_C("blocked");
|
|
402
|
-
} else if (CHARSLICE_EQUALS("wait_readable", name_slice)) { // Expected to be IO#wait_readable
|
|
403
|
-
state_label->str = DDOG_CHARSLICE_C("network");
|
|
404
|
-
} else if (CHARSLICE_EQUALS("_native_idle_sampling_loop", name_slice)) { // Expected to be Datadog::Profiler::Collectors::IdleSamplingHelper#_native_idle_sampling_loop
|
|
405
|
-
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
406
|
-
} else if (CHARSLICE_EQUALS("_native_sampling_loop", name_slice)) { // Expected to be Datadog::Profiler::Collectors::CpuAndWallTimeWorker#_native_sampling_loop
|
|
407
|
-
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
408
|
-
}
|
|
409
|
-
#ifdef NO_PRIMITIVE_POP // Ruby < 3.2
|
|
410
|
-
else if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
|
|
411
|
-
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
412
|
-
}
|
|
413
|
-
#endif
|
|
414
|
-
} else {
|
|
415
|
-
#ifndef NO_PRIMITIVE_POP // Ruby >= 3.2
|
|
416
|
-
if (CHARSLICE_EQUALS("<internal:thread_sync>", filename_slice)) {
|
|
417
|
-
if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
|
|
418
|
-
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
419
|
-
}
|
|
420
|
-
#ifndef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby >= 4
|
|
421
|
-
else if (CHARSLICE_EQUALS("synchronize", name_slice) || CHARSLICE_EQUALS("lock", name_slice)) { // Expected to be Mutex#lock/synchronize
|
|
422
|
-
state_label->str = DDOG_CHARSLICE_C("blocked");
|
|
423
|
-
} else if (CHARSLICE_EQUALS("sleep", name_slice)) { // Expected to be Mutex#sleep
|
|
424
|
-
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
425
|
-
} else if (CHARSLICE_EQUALS("wait", name_slice)) { // Expected to be ConditionVariable#wait
|
|
426
|
-
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
427
|
-
}
|
|
428
|
-
#endif
|
|
429
|
-
}
|
|
430
|
-
#endif
|
|
431
|
-
}
|
|
461
|
+
categorize_sample_state(labels, frame, unqualified_name(cme, iseq), filename_slice);
|
|
432
462
|
}
|
|
433
463
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
frame_name = qualified_name;
|
|
437
|
-
} else {
|
|
438
|
-
frame_name = name_slice;
|
|
439
|
-
}
|
|
464
|
+
if (!name_is_cached) {
|
|
465
|
+
maybe_trim_template_random_ids(&frame_name, filename_slice, name_is_cacheable);
|
|
440
466
|
|
|
441
|
-
|
|
467
|
+
// Keep this name for as long as the frame stays in the buffer
|
|
468
|
+
if (cached_name != NULL && name_is_cacheable && frame_name.len <= MAX_CACHED_FRAME_NAME) {
|
|
469
|
+
memcpy(cached_name, frame_name.ptr, frame_name.len);
|
|
470
|
+
buffer->stack_buffer[i].cached_name_len = frame_name.len;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
442
473
|
|
|
443
474
|
int libdatadog_stores_stacks_flipped_from_rb_profile_frames_index = top_of_stack_position - i;
|
|
444
475
|
|
|
@@ -548,33 +579,56 @@ static const char *get_or_compute_native_filename(void *function, st_table *nati
|
|
|
548
579
|
// the extra "_".)
|
|
549
580
|
//
|
|
550
581
|
// This method trims these suffixes, so that we keep less data + the names correctly aggregate together.
|
|
551
|
-
|
|
582
|
+
//
|
|
583
|
+
// The ids end `frame_name`, or sit right before DDTRACE_BLOCK_SUFFIX
|
|
584
|
+
// ("Foo#_app_views_articles_index_html_erb__123_456 (block)"); in that case we move the suffix left over the ids.
|
|
585
|
+
// That write needs a name we composed ourselves, which is what `frame_name_in_scratch_buffer` tells us.
|
|
586
|
+
static void maybe_trim_template_random_ids(
|
|
587
|
+
ddog_CharSlice *frame_name,
|
|
588
|
+
ddog_CharSlice filename,
|
|
589
|
+
bool frame_name_in_scratch_buffer
|
|
590
|
+
) {
|
|
552
591
|
// Check filename doesn't end with ".rb"; templates are usually along the lines of .html.erb/.html.haml/...
|
|
553
|
-
if (
|
|
592
|
+
if (filename.len < 3 || memcmp(filename.ptr + filename.len - 3, ".rb", 3) == 0) return;
|
|
593
|
+
|
|
594
|
+
if (frame_name->len > 1024) return;
|
|
595
|
+
if (frame_name->len == 0) return;
|
|
596
|
+
|
|
597
|
+
static const char block_suffix[] = DDTRACE_BLOCK_SUFFIX;
|
|
598
|
+
size_t block_suffix_len = sizeof(block_suffix) - 1;
|
|
554
599
|
|
|
555
|
-
|
|
556
|
-
|
|
600
|
+
size_t len = frame_name->len;
|
|
601
|
+
bool has_block_suffix =
|
|
602
|
+
frame_name_in_scratch_buffer &&
|
|
603
|
+
len > block_suffix_len &&
|
|
604
|
+
memcmp(frame_name->ptr + len - block_suffix_len, block_suffix, block_suffix_len) == 0;
|
|
605
|
+
if (has_block_suffix) len -= block_suffix_len;
|
|
557
606
|
|
|
558
|
-
int pos = ((int)
|
|
607
|
+
int pos = ((int) len) - 1;
|
|
559
608
|
|
|
560
609
|
// Let's match on something__number_number:
|
|
561
610
|
// Find start of id suffix from the end...
|
|
562
|
-
if (
|
|
611
|
+
if (frame_name->ptr[pos] < '0' || frame_name->ptr[pos] > '9') return;
|
|
563
612
|
|
|
564
613
|
// ...now match a bunch of numbers and interspersed underscores
|
|
565
614
|
for (int underscores = 0; pos >= 0 && underscores < 2; pos--) {
|
|
566
|
-
if (
|
|
567
|
-
else if (
|
|
615
|
+
if (frame_name->ptr[pos] == '_') underscores++;
|
|
616
|
+
else if (frame_name->ptr[pos] < '0' || frame_name->ptr[pos] > '9') return;
|
|
568
617
|
}
|
|
569
618
|
|
|
570
619
|
// Make sure there's something left before the underscores (hence the <= instead of <) + match the last underscore
|
|
571
|
-
if (pos <= 0 ||
|
|
620
|
+
if (pos <= 0 || frame_name->ptr[pos] != '_') return;
|
|
572
621
|
|
|
573
622
|
// Does it have the optional third underscore? If so, remove it as well
|
|
574
|
-
if (pos > 1 &&
|
|
623
|
+
if (pos > 1 && frame_name->ptr[pos-1] == '_') pos--;
|
|
575
624
|
|
|
576
625
|
// If we got here, we matched on our pattern. Let's slice the length of the string to exclude it.
|
|
577
|
-
|
|
626
|
+
if (has_block_suffix) {
|
|
627
|
+
memcpy((char *) frame_name->ptr + pos, block_suffix, block_suffix_len);
|
|
628
|
+
frame_name->len = pos + block_suffix_len;
|
|
629
|
+
} else {
|
|
630
|
+
frame_name->len = pos;
|
|
631
|
+
}
|
|
578
632
|
}
|
|
579
633
|
|
|
580
634
|
static void add_truncated_frames_placeholder(ddog_prof_Location *locations) {
|
|
@@ -680,7 +734,7 @@ uint16_t sampling_buffer_check_max_frames(int max_frames) {
|
|
|
680
734
|
return max_frames;
|
|
681
735
|
}
|
|
682
736
|
|
|
683
|
-
void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames) {
|
|
737
|
+
void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames, bool cache_names) {
|
|
684
738
|
sampling_buffer_check_max_frames(max_frames);
|
|
685
739
|
|
|
686
740
|
buffer->max_frames = max_frames;
|
|
@@ -688,16 +742,19 @@ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames) {
|
|
|
688
742
|
buffer->pending_sample = false;
|
|
689
743
|
buffer->is_marking = false;
|
|
690
744
|
buffer->pending_sample_result = 0;
|
|
745
|
+
buffer->cached_names = cache_names ? ruby_xcalloc(max_frames, MAX_CACHED_FRAME_NAME) : NULL;
|
|
691
746
|
}
|
|
692
747
|
|
|
693
748
|
void sampling_buffer_free(sampling_buffer *buffer) {
|
|
694
749
|
ruby_xfree(buffer->stack_buffer);
|
|
750
|
+
ruby_xfree(buffer->cached_names);
|
|
695
751
|
|
|
696
752
|
buffer->max_frames = 0;
|
|
697
753
|
buffer->stack_buffer = NULL;
|
|
698
754
|
buffer->pending_sample = false;
|
|
699
755
|
buffer->is_marking = false;
|
|
700
756
|
buffer->pending_sample_result = 0;
|
|
757
|
+
buffer->cached_names = NULL;
|
|
701
758
|
}
|
|
702
759
|
|
|
703
760
|
void sampling_buffer_mark(sampling_buffer *buffer) {
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
#define MAX_FRAMES_LIMIT 3000
|
|
9
9
|
#define MAX_FRAMES_LIMIT_AS_STRING "3000"
|
|
10
10
|
|
|
11
|
+
// Longest qualified frame name we keep per frame in `sampling_buffer`. Longer names are still reported, they just get
|
|
12
|
+
// composed again on every sample; this bounds the per-thread memory the cache costs (max_frames * this).
|
|
13
|
+
#define MAX_CACHED_FRAME_NAME 96
|
|
14
|
+
|
|
11
15
|
// Per thread, where we store the stack sample
|
|
12
16
|
typedef struct {
|
|
13
17
|
uint16_t max_frames;
|
|
@@ -15,6 +19,10 @@ typedef struct {
|
|
|
15
19
|
bool pending_sample;
|
|
16
20
|
bool is_marking; // Used to avoid recording a sample when marking (marking can happen outside of GC as well)
|
|
17
21
|
int pending_sample_result;
|
|
22
|
+
// Qualified frame names from the last sample, MAX_CACHED_FRAME_NAME bytes per frame (NULL when not qualifying names).
|
|
23
|
+
// A frame keeps its name for as long as it stays in `stack_buffer`, which is most of the time: between two samples
|
|
24
|
+
// of a thread, usually only the frames close to the top of the stack change.
|
|
25
|
+
char *cached_names;
|
|
18
26
|
} sampling_buffer;
|
|
19
27
|
|
|
20
28
|
// 1 per ThreadContext so effectively global.
|
|
@@ -55,7 +63,7 @@ void sample_locations_initialize(sample_locations *locations, uint16_t max_frame
|
|
|
55
63
|
void sample_locations_free(sample_locations *locations);
|
|
56
64
|
|
|
57
65
|
uint16_t sampling_buffer_check_max_frames(int max_frames);
|
|
58
|
-
void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames);
|
|
66
|
+
void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames, bool cache_names);
|
|
59
67
|
void sampling_buffer_free(sampling_buffer *buffer);
|
|
60
68
|
void sampling_buffer_mark(sampling_buffer *buffer);
|
|
61
69
|
static inline bool sampling_buffer_needs_marking(sampling_buffer *buffer) {
|
|
@@ -122,6 +122,10 @@ static ID otel_fiber_context_storage_id; // id of :@opentelemetry_context in Rub
|
|
|
122
122
|
// in settings.rb. See `initialize_context` for details on why this is needed/used.
|
|
123
123
|
static uint16_t latest_max_frames = 400;
|
|
124
124
|
|
|
125
|
+
// Same as `latest_max_frames`, for deciding whether new sampling buffers need room to cache qualified frame names.
|
|
126
|
+
// Should be kept in sync with the default for DD_PROFILING_EXPERIMENTAL_SHOW_CLASSES_ENABLED in settings.rb.
|
|
127
|
+
static bool latest_show_classes = true;
|
|
128
|
+
|
|
125
129
|
// Global tracepoint for RUBY_EVENT_THREAD_BEGIN. Created and enabled once when the first ThreadContext collector is initialized.
|
|
126
130
|
static VALUE thread_begin_tracepoint = Qnil;
|
|
127
131
|
|
|
@@ -1265,7 +1269,7 @@ static void initialize_context(VALUE thread, per_thread_context *thread_context,
|
|
|
1265
1269
|
// We always create per_thread_context's with latest_max_frames; that value is kept in sync with the
|
|
1266
1270
|
// active profiler's max_frames by the global reset that runs when profiling starts
|
|
1267
1271
|
// so we expect to always see here the latest correct value to be used.
|
|
1268
|
-
sampling_buffer_initialize(&thread_context->sampling_buffer, latest_max_frames);
|
|
1272
|
+
sampling_buffer_initialize(&thread_context->sampling_buffer, latest_max_frames, latest_show_classes);
|
|
1269
1273
|
|
|
1270
1274
|
snprintf(thread_context->thread_id, THREAD_ID_LIMIT_CHARS, "%"PRIu64" (%lu)", native_thread_id_for(thread), (unsigned long) thread_id_for(thread));
|
|
1271
1275
|
thread_context->thread_id_char_slice = (ddog_CharSlice) {.ptr = thread_context->thread_id, .len = strlen(thread_context->thread_id)};
|
|
@@ -1327,6 +1331,7 @@ void thread_context_collector_reset_all_per_thread_contexts(VALUE self_instance)
|
|
|
1327
1331
|
}
|
|
1328
1332
|
|
|
1329
1333
|
latest_max_frames = state->locations.len;
|
|
1334
|
+
latest_show_classes = state->show_classes;
|
|
1330
1335
|
|
|
1331
1336
|
long current_monotonic_wall_time_ns = monotonic_wall_time_now_ns();
|
|
1332
1337
|
|
|
@@ -20,7 +20,7 @@ def skip_building_extension!(reason)
|
|
|
20
20
|
Datadog::Profiling::NativeExtensionHelpers::Supported.failure_banner_for(
|
|
21
21
|
**reason,
|
|
22
22
|
fail_install: fail_install_if_missing_extension,
|
|
23
|
-
)
|
|
23
|
+
),
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
File.write(
|
|
@@ -32,7 +32,7 @@ def skip_building_extension!(reason)
|
|
|
32
32
|
require "mkmf"
|
|
33
33
|
Logging.message(
|
|
34
34
|
"[datadog] Failure cause: " \
|
|
35
|
-
"#{Datadog::Profiling::NativeExtensionHelpers::Supported.render_skipped_reason_file(**reason)}\n"
|
|
35
|
+
"#{Datadog::Profiling::NativeExtensionHelpers::Supported.render_skipped_reason_file(**reason)}\n",
|
|
36
36
|
)
|
|
37
37
|
else
|
|
38
38
|
File.write("Makefile", "all install clean: # dummy makefile that does nothing")
|
|
@@ -63,7 +63,7 @@ $stderr.puts(
|
|
|
63
63
|
| Thanks for using datadog! You rock! |
|
|
64
64
|
+------------------------------------------------------------------------------+
|
|
65
65
|
|
|
66
|
-
)
|
|
66
|
+
),
|
|
67
67
|
)
|
|
68
68
|
|
|
69
69
|
# NOTE: we MUST NOT require 'mkmf' before we check the #skip_building_extension? because the require triggers checks
|
|
@@ -89,12 +89,10 @@ append_cflags "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
|
|
|
89
89
|
# header lands upstream in libdatadog/libdatadog-rb. Remove this once that ships.
|
|
90
90
|
append_cflags "-Wno-error=typedef-redefinition" if ENV["DATADOG_GEM_CI"] == "true"
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
# @ivoanjo: We could probably start using C11/gnu11 for non macOS-too but it's somewhat hard to validate so I chickened out for now
|
|
97
|
-
append_cflags RUBY_PLATFORM.include?("darwin") ? "-std=gnu11" : "-std=gnu99"
|
|
92
|
+
unless try_cflags("-std=gnu11") && have_type("atomic_int", ["stdatomic.h"])
|
|
93
|
+
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_C11_MISSING)
|
|
94
|
+
end
|
|
95
|
+
$CFLAGS += " -std=gnu11"
|
|
98
96
|
|
|
99
97
|
# Gets really noisy when we include the private VM headers, let's omit it (TODO: Use #pragma GCC diagnostic instead?)
|
|
100
98
|
append_cflags "-Wno-unused-function"
|
|
@@ -225,10 +223,6 @@ end
|
|
|
225
223
|
|
|
226
224
|
Datadog::LibdatadogExtconfHelpers.add_libdatadog_version_define
|
|
227
225
|
|
|
228
|
-
unless have_type("atomic_int", ["stdatomic.h"])
|
|
229
|
-
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
|
|
230
|
-
end
|
|
231
|
-
|
|
232
226
|
# Tag the native extension library with the Ruby version and Ruby platform.
|
|
233
227
|
# This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
|
|
234
228
|
# the wrong library is never loaded.
|
|
@@ -94,9 +94,9 @@ module Datadog
|
|
|
94
94
|
)
|
|
95
95
|
|
|
96
96
|
# Validation for this check is done in extconf.rb because it relies on mkmf
|
|
97
|
-
|
|
98
|
-
"your C compiler
|
|
99
|
-
"This issue can
|
|
97
|
+
COMPILER_C11_MISSING = explain_issue(
|
|
98
|
+
"your C compiler does not support C11 (-std=gnu11).",
|
|
99
|
+
"This issue can be fixed by upgrading to a later version of your",
|
|
100
100
|
"operating system image or compiler.",
|
|
101
101
|
suggested: CONTACT_SUPPORT,
|
|
102
102
|
)
|