datadog 2.3.0 → 2.5.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 +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)
|