datadog 2.3.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +64 -2
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +10 -22
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +3 -3
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +198 -41
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
- data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +645 -107
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +15 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
- data/ext/datadog_profiling_native_extension/extconf.rb +42 -25
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +194 -34
- data/ext/datadog_profiling_native_extension/heap_recorder.h +11 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +1 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +53 -2
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +14 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +58 -22
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/libdatadog_api/crashtracker.c +20 -18
- data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
- data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
- data/lib/datadog/appsec/component.rb +29 -8
- data/lib/datadog/appsec/configuration/settings.rb +10 -2
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +14 -15
- data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +7 -20
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -15
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +6 -18
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +7 -20
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +5 -18
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -5
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +5 -18
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -10
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +7 -20
- data/lib/datadog/appsec/event.rb +25 -1
- data/lib/datadog/appsec/ext.rb +4 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -5
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +7 -20
- data/lib/datadog/appsec/processor/context.rb +109 -0
- data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
- data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
- data/lib/datadog/appsec/processor.rb +42 -107
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec/scope.rb +1 -4
- data/lib/datadog/appsec/utils/trace_operation.rb +15 -0
- data/lib/datadog/appsec/utils.rb +2 -0
- data/lib/datadog/appsec.rb +3 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +26 -25
- data/lib/datadog/core/configuration/components.rb +4 -3
- data/lib/datadog/core/configuration/settings.rb +96 -5
- data/lib/datadog/core/configuration.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +9 -6
- data/lib/datadog/core/environment/execution.rb +5 -5
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/metrics/client.rb +7 -0
- data/lib/datadog/core/rate_limiter.rb +183 -0
- data/lib/datadog/core/remote/client/capabilities.rb +4 -3
- data/lib/datadog/core/remote/component.rb +4 -2
- data/lib/datadog/core/remote/negotiation.rb +4 -4
- data/lib/datadog/core/remote/tie.rb +2 -0
- data/lib/datadog/core/remote/transport/http.rb +5 -0
- data/lib/datadog/core/remote/worker.rb +1 -1
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +5 -1
- data/lib/datadog/core/semaphore.rb +35 -0
- data/lib/datadog/core/telemetry/component.rb +2 -0
- data/lib/datadog/core/telemetry/event.rb +12 -7
- data/lib/datadog/core/telemetry/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +50 -14
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/transport/ext.rb +1 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/di/code_tracker.rb +166 -0
- data/lib/datadog/di/configuration/settings.rb +163 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/error.rb +31 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/instrumenter.rb +301 -0
- data/lib/datadog/di/probe.rb +162 -0
- data/lib/datadog/di/probe_builder.rb +47 -0
- data/lib/datadog/di/probe_notification_builder.rb +207 -0
- data/lib/datadog/di/probe_notifier_worker.rb +244 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +215 -0
- data/lib/datadog/di/transport.rb +67 -0
- data/lib/datadog/di/utils.rb +39 -0
- data/lib/datadog/di.rb +57 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
- data/lib/datadog/profiling/collectors/info.rb +12 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +32 -8
- data/lib/datadog/profiling/component.rb +21 -4
- data/lib/datadog/profiling/http_transport.rb +6 -1
- data/lib/datadog/profiling/scheduler.rb +2 -0
- data/lib/datadog/profiling/stack_recorder.rb +40 -9
- data/lib/datadog/single_step_instrument.rb +12 -0
- data/lib/datadog/tracing/component.rb +13 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +12 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +24 -2
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +9 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +22 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +9 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +3 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
- data/lib/datadog/tracing/distributed/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/ext.rb +2 -0
- data/lib/datadog/tracing/remote.rb +5 -2
- data/lib/datadog/tracing/sampling/matcher.rb +6 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +2 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +15 -9
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +29 -22
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/http.rb +4 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +2 -2
- data/lib/datadog/tracing/writer.rb +26 -28
- data/lib/datadog/version.rb +1 -1
- metadata +40 -15
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -20,17 +20,41 @@ module Datadog
|
|
20
20
|
tracer:,
|
21
21
|
endpoint_collection_enabled:,
|
22
22
|
timeline_enabled:,
|
23
|
-
|
23
|
+
waiting_for_gvl_threshold_ns:,
|
24
|
+
otel_context_enabled:
|
24
25
|
)
|
25
26
|
tracer_context_key = safely_extract_context_key_from(tracer)
|
26
27
|
self.class._native_initialize(
|
27
|
-
self,
|
28
|
-
recorder,
|
29
|
-
max_frames,
|
30
|
-
tracer_context_key,
|
31
|
-
endpoint_collection_enabled,
|
32
|
-
timeline_enabled,
|
33
|
-
|
28
|
+
self_instance: self,
|
29
|
+
recorder: recorder,
|
30
|
+
max_frames: max_frames,
|
31
|
+
tracer_context_key: tracer_context_key,
|
32
|
+
endpoint_collection_enabled: endpoint_collection_enabled,
|
33
|
+
timeline_enabled: timeline_enabled,
|
34
|
+
waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
|
35
|
+
otel_context_enabled: otel_context_enabled,
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.for_testing(
|
40
|
+
recorder:,
|
41
|
+
max_frames: 400,
|
42
|
+
tracer: nil,
|
43
|
+
endpoint_collection_enabled: false,
|
44
|
+
timeline_enabled: false,
|
45
|
+
waiting_for_gvl_threshold_ns: 10_000_000,
|
46
|
+
otel_context_enabled: false,
|
47
|
+
**options
|
48
|
+
)
|
49
|
+
new(
|
50
|
+
recorder: recorder,
|
51
|
+
max_frames: max_frames,
|
52
|
+
tracer: tracer,
|
53
|
+
endpoint_collection_enabled: endpoint_collection_enabled,
|
54
|
+
timeline_enabled: timeline_enabled,
|
55
|
+
waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
|
56
|
+
otel_context_enabled: otel_context_enabled,
|
57
|
+
**options,
|
34
58
|
)
|
35
59
|
end
|
36
60
|
|
@@ -53,6 +53,7 @@ module Datadog
|
|
53
53
|
heap_size_enabled: heap_size_profiling_enabled,
|
54
54
|
heap_sample_every: heap_sample_every,
|
55
55
|
timeline_enabled: timeline_enabled,
|
56
|
+
heap_clean_after_gc_enabled: settings.profiling.advanced.heap_clean_after_gc_enabled,
|
56
57
|
)
|
57
58
|
thread_context_collector = build_thread_context_collector(settings, recorder, optional_tracer, timeline_enabled)
|
58
59
|
worker = Datadog::Profiling::Collectors::CpuAndWallTimeWorker.new(
|
@@ -62,6 +63,7 @@ module Datadog
|
|
62
63
|
dynamic_sampling_rate_overhead_target_percentage: overhead_target_percentage,
|
63
64
|
allocation_profiling_enabled: allocation_profiling_enabled,
|
64
65
|
allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled,
|
66
|
+
gvl_profiling_enabled: enable_gvl_profiling?(settings),
|
65
67
|
)
|
66
68
|
|
67
69
|
internal_metadata = {
|
@@ -89,6 +91,8 @@ module Datadog
|
|
89
91
|
tracer: optional_tracer,
|
90
92
|
endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled,
|
91
93
|
timeline_enabled: timeline_enabled,
|
94
|
+
waiting_for_gvl_threshold_ns: settings.profiling.advanced.waiting_for_gvl_threshold_ns,
|
95
|
+
otel_context_enabled: settings.profiling.advanced.preview_otel_context_enabled,
|
92
96
|
)
|
93
97
|
end
|
94
98
|
|
@@ -252,6 +256,7 @@ module Datadog
|
|
252
256
|
legacy_ruby_that_should_use_workaround = RUBY_VERSION.start_with?("2.5.")
|
253
257
|
|
254
258
|
unless [true, false, :auto].include?(setting_value)
|
259
|
+
# TODO: Replace with a warning instead.
|
255
260
|
Datadog.logger.error(
|
256
261
|
"Ignoring invalid value for profiling no_signals_workaround_enabled setting: #{setting_value.inspect}. " \
|
257
262
|
"Valid options are `true`, `false` or (default) `:auto`."
|
@@ -394,6 +399,7 @@ module Datadog
|
|
394
399
|
if overhead_target_percentage > 0 && overhead_target_percentage <= 20
|
395
400
|
overhead_target_percentage
|
396
401
|
else
|
402
|
+
# TODO: Replace with a warning instead.
|
397
403
|
Datadog.logger.error(
|
398
404
|
"Ignoring invalid value for profiling overhead_target_percentage setting: " \
|
399
405
|
"#{overhead_target_percentage.inspect}. Falling back to default value."
|
@@ -433,13 +439,24 @@ module Datadog
|
|
433
439
|
end
|
434
440
|
|
435
441
|
private_class_method def self.dir_interruption_workaround_enabled?(settings, no_signals_workaround_enabled)
|
436
|
-
return false if no_signals_workaround_enabled
|
437
|
-
|
438
|
-
# NOTE: In the future this method will evolve to check for Ruby versions affected and not apply the workaround
|
439
|
-
# when it's not needed but currently all known Ruby versions are affected.
|
442
|
+
return false if no_signals_workaround_enabled || RUBY_VERSION >= "3.4"
|
440
443
|
|
441
444
|
settings.profiling.advanced.dir_interruption_workaround_enabled
|
442
445
|
end
|
446
|
+
|
447
|
+
private_class_method def self.enable_gvl_profiling?(settings)
|
448
|
+
if RUBY_VERSION < "3.2"
|
449
|
+
if settings.profiling.advanced.preview_gvl_enabled
|
450
|
+
Datadog.logger.warn("GVL profiling is currently not supported in Ruby < 3.2 and will not be enabled.")
|
451
|
+
end
|
452
|
+
|
453
|
+
return false
|
454
|
+
end
|
455
|
+
|
456
|
+
# GVL profiling only makes sense in the context of timeline. We could emit a warning here, but not sure how
|
457
|
+
# useful it is -- if a customer disables timeline, there's nowhere to look for GVL profiling anyway!
|
458
|
+
settings.profiling.advanced.timeline_enabled && settings.profiling.advanced.preview_gvl_enabled
|
459
|
+
end
|
443
460
|
end
|
444
461
|
end
|
445
462
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../core/transport/ext"
|
4
|
+
require_relative "../core/telemetry/logger"
|
4
5
|
|
5
6
|
module Datadog
|
6
7
|
module Profiling
|
@@ -60,10 +61,14 @@ module Datadog
|
|
60
61
|
"Failed to report profiling data (#{config_without_api_key}): " \
|
61
62
|
"server returned unexpected HTTP #{result} status code"
|
62
63
|
)
|
64
|
+
Datadog::Core::Telemetry::Logger.error(
|
65
|
+
"Failed to report profiling data: unexpected HTTP #{result} status code"
|
66
|
+
)
|
63
67
|
false
|
64
68
|
end
|
65
69
|
else
|
66
70
|
Datadog.logger.error("Failed to report profiling data (#{config_without_api_key}): #{result}")
|
71
|
+
Datadog::Core::Telemetry::Logger.error("Failed to report profiling data")
|
67
72
|
false
|
68
73
|
end
|
69
74
|
end
|
@@ -134,7 +139,7 @@ module Datadog
|
|
134
139
|
end
|
135
140
|
|
136
141
|
def config_without_api_key
|
137
|
-
[exporter_configuration[
|
142
|
+
"#{exporter_configuration[0]}: #{exporter_configuration[1]}"
|
138
143
|
end
|
139
144
|
end
|
140
145
|
end
|
@@ -4,6 +4,7 @@ require_relative "../core/utils/time"
|
|
4
4
|
|
5
5
|
require_relative "../core/worker"
|
6
6
|
require_relative "../core/workers/polling"
|
7
|
+
require_relative "../core/telemetry/logger"
|
7
8
|
|
8
9
|
module Datadog
|
9
10
|
module Profiling
|
@@ -134,6 +135,7 @@ module Datadog
|
|
134
135
|
Datadog.logger.error(
|
135
136
|
"Unable to report profile. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
136
137
|
)
|
138
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "Unable to report profile")
|
137
139
|
end
|
138
140
|
|
139
141
|
true
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../core/telemetry/logger"
|
4
|
+
|
3
5
|
module Datadog
|
4
6
|
module Profiling
|
5
7
|
# Stores stack samples in a native libdatadog data structure and expose Ruby-level serialization APIs
|
@@ -7,8 +9,13 @@ module Datadog
|
|
7
9
|
# Methods prefixed with _native_ are implemented in `stack_recorder.c`
|
8
10
|
class StackRecorder
|
9
11
|
def initialize(
|
10
|
-
cpu_time_enabled:,
|
11
|
-
|
12
|
+
cpu_time_enabled:,
|
13
|
+
alloc_samples_enabled:,
|
14
|
+
heap_samples_enabled:,
|
15
|
+
heap_size_enabled:,
|
16
|
+
heap_sample_every:,
|
17
|
+
timeline_enabled:,
|
18
|
+
heap_clean_after_gc_enabled:
|
12
19
|
)
|
13
20
|
# This mutex works in addition to the fancy C-level mutexes we have in the native side (see the docs there).
|
14
21
|
# It prevents multiple Ruby threads calling serialize at the same time -- something like
|
@@ -19,13 +26,36 @@ module Datadog
|
|
19
26
|
@no_concurrent_synchronize_mutex = Mutex.new
|
20
27
|
|
21
28
|
self.class._native_initialize(
|
22
|
-
self,
|
23
|
-
cpu_time_enabled,
|
24
|
-
alloc_samples_enabled,
|
25
|
-
heap_samples_enabled,
|
26
|
-
heap_size_enabled,
|
27
|
-
heap_sample_every,
|
28
|
-
timeline_enabled,
|
29
|
+
self_instance: self,
|
30
|
+
cpu_time_enabled: cpu_time_enabled,
|
31
|
+
alloc_samples_enabled: alloc_samples_enabled,
|
32
|
+
heap_samples_enabled: heap_samples_enabled,
|
33
|
+
heap_size_enabled: heap_size_enabled,
|
34
|
+
heap_sample_every: heap_sample_every,
|
35
|
+
timeline_enabled: timeline_enabled,
|
36
|
+
heap_clean_after_gc_enabled: heap_clean_after_gc_enabled,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.for_testing(
|
41
|
+
cpu_time_enabled: true,
|
42
|
+
alloc_samples_enabled: false,
|
43
|
+
heap_samples_enabled: false,
|
44
|
+
heap_size_enabled: false,
|
45
|
+
heap_sample_every: 1,
|
46
|
+
timeline_enabled: false,
|
47
|
+
heap_clean_after_gc_enabled: true,
|
48
|
+
**options
|
49
|
+
)
|
50
|
+
new(
|
51
|
+
cpu_time_enabled: cpu_time_enabled,
|
52
|
+
alloc_samples_enabled: alloc_samples_enabled,
|
53
|
+
heap_samples_enabled: heap_samples_enabled,
|
54
|
+
heap_size_enabled: heap_size_enabled,
|
55
|
+
heap_sample_every: heap_sample_every,
|
56
|
+
timeline_enabled: timeline_enabled,
|
57
|
+
heap_clean_after_gc_enabled: heap_clean_after_gc_enabled,
|
58
|
+
**options,
|
29
59
|
)
|
30
60
|
end
|
31
61
|
|
@@ -42,6 +72,7 @@ module Datadog
|
|
42
72
|
error_message = result
|
43
73
|
|
44
74
|
Datadog.logger.error("Failed to serialize profiling data: #{error_message}")
|
75
|
+
Datadog::Core::Telemetry::Logger.error("Failed to serialize profiling data")
|
45
76
|
|
46
77
|
nil
|
47
78
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Entrypoint file for single step instrumentation.
|
5
|
+
#
|
6
|
+
# This file's path is private. Do not reference this file.
|
7
|
+
#
|
8
|
+
begin
|
9
|
+
require_relative 'auto_instrument'
|
10
|
+
rescue StandardError, LoadError => e
|
11
|
+
warn "Single step instrumentation failed: #{e.class}:#{e.message}\n\tSource:\n\t#{Array(e.backtrace).join("\n\t")}"
|
12
|
+
end
|
@@ -73,6 +73,19 @@ module Datadog
|
|
73
73
|
return sampler
|
74
74
|
end
|
75
75
|
|
76
|
+
# AppSec events are sent to the backend using traces.
|
77
|
+
# Standalone ASM billing means that we don't want to charge clients for APM traces,
|
78
|
+
# so we want to send the minimum amount of traces possible (idealy only traces that contains security events),
|
79
|
+
# but for features such as API Security, we need to send at least one trace per minute,
|
80
|
+
# to keep the service alive on the backend side.
|
81
|
+
if settings.appsec.standalone.enabled
|
82
|
+
post_sampler = Tracing::Sampling::RuleSampler.new(
|
83
|
+
[Tracing::Sampling::SimpleRule.new(sample_rate: 1.0)],
|
84
|
+
rate_limiter: Datadog::Core::TokenBucket.new(1.0 / 60, 1.0),
|
85
|
+
default_sample_rate: 1.0 / 60
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
76
89
|
# Sampling rules are provided
|
77
90
|
if (rules = settings.tracing.sampling.rules)
|
78
91
|
post_sampler = Tracing::Sampling::RuleSampler.parse(
|
@@ -14,21 +14,17 @@ module Datadog
|
|
14
14
|
module ActionCableConnection
|
15
15
|
def on_open
|
16
16
|
Tracing.trace(Ext::SPAN_ON_OPEN) do |span, trace|
|
17
|
-
|
18
|
-
|
19
|
-
span.type = Tracing::Metadata::Ext::AppTypes::TYPE_WEB
|
17
|
+
span.resource = "#{self.class}#on_open"
|
18
|
+
span.type = Tracing::Metadata::Ext::AppTypes::TYPE_WEB
|
20
19
|
|
21
|
-
|
22
|
-
|
20
|
+
span.set_tag(Ext::TAG_ACTION, 'on_open')
|
21
|
+
span.set_tag(Ext::TAG_CONNECTION, self.class.to_s)
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
|
24
|
+
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ON_OPEN)
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
rescue StandardError => e
|
30
|
-
Datadog.logger.error("Error preparing span for ActionCable::Connection: #{e}")
|
31
|
-
end
|
26
|
+
# Set the resource name of the trace
|
27
|
+
trace.resource = span.resource
|
32
28
|
|
33
29
|
super
|
34
30
|
end
|
@@ -7,6 +7,7 @@ require_relative '../ext'
|
|
7
7
|
require_relative '../utils'
|
8
8
|
require_relative '../../rack/middlewares'
|
9
9
|
require_relative '../../analytics'
|
10
|
+
require_relative '../../../../core/telemetry/logger'
|
10
11
|
|
11
12
|
module Datadog
|
12
13
|
module Tracing
|
@@ -43,6 +44,7 @@ module Datadog
|
|
43
44
|
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CONTROLLER)
|
44
45
|
rescue StandardError => e
|
45
46
|
Datadog.logger.error(e.message)
|
47
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
46
48
|
end
|
47
49
|
|
48
50
|
def finish_processing(payload)
|
@@ -81,10 +83,13 @@ module Datadog
|
|
81
83
|
end
|
82
84
|
rescue StandardError => e
|
83
85
|
Datadog.logger.error(e.message)
|
86
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
84
87
|
end
|
85
88
|
|
86
89
|
# Instrumentation for ActionController::Metal
|
87
90
|
module Metal
|
91
|
+
# TODO: Refactor this method to avoid using async API that splits the logic
|
92
|
+
# into two different methods (`start_processing` and `finish_processing`)
|
88
93
|
def process_action(*args)
|
89
94
|
# mutable payload with a tracing context that is used in two different
|
90
95
|
# signals; it propagates the request span so that it can be finished
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../metadata/ext'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Tracing
|
7
|
+
module Contrib
|
8
|
+
module ActionPack
|
9
|
+
module ActionDispatch
|
10
|
+
# Instrumentation for ActionDispatch components
|
11
|
+
module Instrumentation
|
12
|
+
module_function
|
13
|
+
|
14
|
+
def set_http_route_tags(route_spec, script_name)
|
15
|
+
return unless Tracing.enabled?
|
16
|
+
|
17
|
+
return unless route_spec
|
18
|
+
|
19
|
+
request_trace = Tracing.active_trace
|
20
|
+
return unless request_trace
|
21
|
+
|
22
|
+
request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, route_spec.to_s.gsub(/\(.:format\)\z/, ''))
|
23
|
+
|
24
|
+
if script_name && !script_name.empty?
|
25
|
+
request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, script_name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def dispatcher_route?(route)
|
30
|
+
return true if route.dispatcher?
|
31
|
+
|
32
|
+
# in Rails 4 there is no #rack_app method on the app
|
33
|
+
return true if route.app.respond_to?(:rack_app) && !route.app.rack_app.nil?
|
34
|
+
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
# Instrumentation for ActionDispatch::Journey components
|
39
|
+
module Journey
|
40
|
+
# Instrumentation for ActionDispatch::Journey::Router for Rails versions older than 7.1
|
41
|
+
module Router
|
42
|
+
def find_routes(req)
|
43
|
+
result = super
|
44
|
+
|
45
|
+
# result is an array of [match, parameters, route] tuples
|
46
|
+
routes = result.map(&:last)
|
47
|
+
|
48
|
+
routes.each do |route|
|
49
|
+
if Instrumentation.dispatcher_route?(route)
|
50
|
+
Instrumentation.set_http_route_tags(route.path.spec, req.env['SCRIPT_NAME'])
|
51
|
+
break
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Since Rails 7.1 `Router#find_routes` makes the route computation lazy
|
60
|
+
# https://github.com/rails/rails/commit/35b280fcc2d5d474f9f2be3aca3ae7aa6bba66eb
|
61
|
+
module LazyRouter
|
62
|
+
def find_routes(req)
|
63
|
+
super do |match, parameters, route|
|
64
|
+
if Instrumentation.dispatcher_route?(route)
|
65
|
+
Instrumentation.set_http_route_tags(route.path.spec, req.env['SCRIPT_NAME'])
|
66
|
+
end
|
67
|
+
|
68
|
+
yield [match, parameters, route]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../patcher'
|
4
|
+
require_relative 'instrumentation'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module Tracing
|
8
|
+
module Contrib
|
9
|
+
module ActionPack
|
10
|
+
module ActionDispatch
|
11
|
+
# Patcher for ActionController components
|
12
|
+
module Patcher
|
13
|
+
include Contrib::Patcher
|
14
|
+
|
15
|
+
module_function
|
16
|
+
|
17
|
+
def target_version
|
18
|
+
Integration.version
|
19
|
+
end
|
20
|
+
|
21
|
+
def patch
|
22
|
+
if ::ActionPack.gem_version >= Gem::Version.new('7.1')
|
23
|
+
::ActionDispatch::Journey::Router.prepend(ActionDispatch::Instrumentation::Journey::LazyRouter)
|
24
|
+
else
|
25
|
+
::ActionDispatch::Journey::Router.prepend(ActionDispatch::Instrumentation::Journey::Router)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../patcher'
|
4
4
|
require_relative 'action_controller/patcher'
|
5
|
+
require_relative 'action_dispatch/patcher'
|
5
6
|
|
6
7
|
module Datadog
|
7
8
|
module Tracing
|
@@ -19,6 +20,7 @@ module Datadog
|
|
19
20
|
|
20
21
|
def patch
|
21
22
|
ActionController::Patcher.patch
|
23
|
+
ActionDispatch::Patcher.patch
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../configuration/resolver'
|
4
4
|
require_relative 'makara_resolver'
|
5
|
+
require_relative '../../../../core/telemetry/logger'
|
5
6
|
|
6
7
|
module Datadog
|
7
8
|
module Tracing
|
@@ -72,10 +73,12 @@ module Datadog
|
|
72
73
|
#
|
73
74
|
# `db_config` input may contain sensitive information such as passwords,
|
74
75
|
# hence provide a succinct summary for the error logging.
|
76
|
+
#
|
75
77
|
Datadog.logger.error(
|
76
78
|
'Failed to resolve ActiveRecord database configuration. '\
|
77
79
|
"Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
|
78
80
|
)
|
81
|
+
Core::Telemetry::Logger.report(e, description: 'Failed to resolve ActiveRecord database configuration')
|
79
82
|
|
80
83
|
nil
|
81
84
|
end
|
@@ -95,6 +98,7 @@ module Datadog
|
|
95
98
|
"Failed to resolve key #{matcher.inspect}. " \
|
96
99
|
"Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
|
97
100
|
)
|
101
|
+
Core::Telemetry::Logger.report(e, description: 'Failed to resolve key')
|
98
102
|
|
99
103
|
nil
|
100
104
|
end
|
@@ -4,6 +4,7 @@ require_relative '../../../metadata/ext'
|
|
4
4
|
require_relative '../../analytics'
|
5
5
|
require_relative '../ext'
|
6
6
|
require_relative '../event'
|
7
|
+
require_relative '../../../../core/telemetry/logger'
|
7
8
|
|
8
9
|
module Datadog
|
9
10
|
module Tracing
|
@@ -48,7 +49,8 @@ module Datadog
|
|
48
49
|
span.set_tag(Ext::TAG_INSTANTIATION_CLASS_NAME, payload.fetch(:class_name))
|
49
50
|
span.set_tag(Ext::TAG_INSTANTIATION_RECORD_COUNT, payload.fetch(:record_count))
|
50
51
|
rescue StandardError => e
|
51
|
-
Datadog.logger.
|
52
|
+
Datadog.logger.error(e.message)
|
53
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
@@ -6,6 +6,7 @@ require_relative '../event'
|
|
6
6
|
require_relative '../ext'
|
7
7
|
require_relative '../../analytics'
|
8
8
|
require_relative '../../utils/database'
|
9
|
+
require_relative '../../../../core/telemetry/logger'
|
9
10
|
|
10
11
|
module Datadog
|
11
12
|
module Tracing
|
@@ -68,7 +69,8 @@ module Datadog
|
|
68
69
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, config[:host]) if config[:host]
|
69
70
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, config[:port]) if config[:port]
|
70
71
|
rescue StandardError => e
|
71
|
-
Datadog.logger.
|
72
|
+
Datadog.logger.error(e.message)
|
73
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
72
74
|
end
|
73
75
|
end
|
74
76
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../ext'
|
4
4
|
require_relative '../event'
|
5
|
+
require_relative '../../../../../core/telemetry/logger'
|
5
6
|
|
6
7
|
module Datadog
|
7
8
|
module Tracing
|
@@ -64,7 +65,7 @@ module Datadog
|
|
64
65
|
key = payload[:key]
|
65
66
|
store = payload[:store]
|
66
67
|
|
67
|
-
mapping = MAPPING
|
68
|
+
mapping = MAPPING.fetch(event)
|
68
69
|
|
69
70
|
span.service = configuration[:cache_service]
|
70
71
|
span.resource = mapping[:resource]
|
@@ -81,6 +82,9 @@ module Datadog
|
|
81
82
|
span.set_tag('EVENT', event)
|
82
83
|
|
83
84
|
set_cache_key(span, key, mapping[:multi_key])
|
85
|
+
rescue StandardError => e
|
86
|
+
Datadog.logger.error(e.message)
|
87
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
84
88
|
end
|
85
89
|
|
86
90
|
def set_cache_key(span, key, multi_key)
|
@@ -29,6 +29,7 @@ module Datadog
|
|
29
29
|
private
|
30
30
|
|
31
31
|
# rubocop:disable Metrics/AbcSize
|
32
|
+
# rubocop:disable Metrics/MethodLength
|
32
33
|
def annotate!(span, context)
|
33
34
|
span.service = configuration[:service_name]
|
34
35
|
span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
|
@@ -76,7 +77,11 @@ module Datadog
|
|
76
77
|
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, context.safely(:status_code))
|
77
78
|
|
78
79
|
Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
|
80
|
+
rescue StandardError => e
|
81
|
+
Datadog.logger.error(e.message)
|
82
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
79
83
|
end
|
84
|
+
# rubocop:enable Metrics/MethodLength
|
80
85
|
# rubocop:enable Metrics/AbcSize
|
81
86
|
|
82
87
|
def configuration
|
@@ -93,11 +93,16 @@ module Datadog
|
|
93
93
|
span.resource = "#{method} #{quantized_url}"
|
94
94
|
Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
|
95
95
|
rescue StandardError => e
|
96
|
+
# TODO: Refactor the code to streamline the execution without ensure
|
96
97
|
Datadog.logger.error(e.message)
|
98
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
97
99
|
ensure
|
98
100
|
# the call is still executed
|
99
101
|
response = super
|
100
|
-
|
102
|
+
|
103
|
+
if response && response.respond_to?(:status)
|
104
|
+
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.status)
|
105
|
+
end
|
101
106
|
end
|
102
107
|
end
|
103
108
|
response
|
@@ -110,6 +110,10 @@ module Datadog
|
|
110
110
|
|
111
111
|
datadog_tag_request
|
112
112
|
|
113
|
+
if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(datadog_trace)
|
114
|
+
datadog_trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
|
115
|
+
end
|
116
|
+
|
113
117
|
if datadog_configuration[:distributed_tracing]
|
114
118
|
@datadog_original_headers ||= {}
|
115
119
|
Contrib::HTTP.inject(datadog_trace, @datadog_original_headers)
|
@@ -30,6 +30,9 @@ module Datadog
|
|
30
30
|
trace = Tracing.active_trace
|
31
31
|
datum[:datadog_span] = span
|
32
32
|
annotate!(span, datum)
|
33
|
+
if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
|
34
|
+
trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
|
35
|
+
end
|
33
36
|
propagate!(trace, span, datum) if distributed_tracing?
|
34
37
|
|
35
38
|
span
|
@@ -7,6 +7,7 @@ require_relative '../http'
|
|
7
7
|
require_relative '../analytics'
|
8
8
|
require_relative 'ext'
|
9
9
|
require_relative '../http_annotation_helper'
|
10
|
+
require_relative '../../../core/telemetry/logger'
|
10
11
|
|
11
12
|
module Datadog
|
12
13
|
module Tracing
|
@@ -28,6 +29,9 @@ module Datadog
|
|
28
29
|
|
29
30
|
Tracing.trace(Ext::SPAN_REQUEST, on_error: request_options[:on_error]) do |span, trace|
|
30
31
|
annotate!(span, env, request_options)
|
32
|
+
if Datadog::AppSec::Utils::TraceOperation.appsec_standalone_reject?(trace)
|
33
|
+
trace.sampling_priority = Tracing::Sampling::Ext::Priority::AUTO_REJECT
|
34
|
+
end
|
31
35
|
propagate!(trace, span, env) if request_options[:distributed_tracing] && Tracing.enabled?
|
32
36
|
app.call(env).on_complete { |resp| handle_response(span, resp, request_options) }
|
33
37
|
end
|
@@ -37,6 +41,7 @@ module Datadog
|
|
37
41
|
|
38
42
|
attr_reader :app
|
39
43
|
|
44
|
+
# rubocop:disable Metrics/AbcSize
|
40
45
|
def annotate!(span, env, options)
|
41
46
|
span.resource = resource_name(env)
|
42
47
|
span.service = service_name(env[:url].host, options)
|
@@ -75,7 +80,11 @@ module Datadog
|
|
75
80
|
)
|
76
81
|
|
77
82
|
Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
|
83
|
+
rescue StandardError => e
|
84
|
+
Datadog.logger.error(e.message)
|
85
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
78
86
|
end
|
87
|
+
# rubocop:enable Metrics/AbcSize
|
79
88
|
|
80
89
|
def handle_response(span, env, options)
|
81
90
|
span.set_error(["Error #{env[:status]}", env[:body]]) if options[:error_status_codes].include? env[:status]
|
@@ -85,6 +94,9 @@ module Datadog
|
|
85
94
|
span.set_tags(
|
86
95
|
Datadog.configuration.tracing.header_tags.response_tags(env[:response_headers])
|
87
96
|
)
|
97
|
+
rescue StandardError => e
|
98
|
+
Datadog.logger.error(e.message)
|
99
|
+
Datadog::Core::Telemetry::Logger.report(e)
|
88
100
|
end
|
89
101
|
|
90
102
|
def propagate!(trace, span, env)
|