datadog 2.17.0 → 2.19.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 +90 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +63 -56
- data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -76
- data/ext/datadog_profiling_native_extension/collectors_stack.h +20 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +62 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +239 -363
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +38 -26
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -4
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +154 -57
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/library_config.c +54 -12
- data/ext/libdatadog_api/library_config.h +6 -0
- data/ext/libdatadog_api/process_discovery.c +2 -7
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/lru_cache.rb +9 -2
- data/lib/datadog/appsec/api_security/route_extractor.rb +71 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +14 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/component.rb +30 -54
- data/lib/datadog/appsec/configuration/settings.rb +60 -2
- data/lib/datadog/appsec/context.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +27 -16
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
- data/lib/datadog/appsec/remote.rb +15 -55
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +10 -11
- data/lib/datadog/appsec.rb +4 -7
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +1 -43
- data/lib/datadog/core/configuration/components.rb +2 -4
- data/lib/datadog/core/configuration/option.rb +9 -9
- data/lib/datadog/core/configuration/settings.rb +42 -10
- data/lib/datadog/core/configuration/stable_config.rb +1 -2
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +5 -1
- data/lib/datadog/core/remote/configuration/repository.rb +12 -0
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +8 -4
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +1 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +148 -40
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +11 -5
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/builder.rb +2 -2
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/utils.rb +7 -0
- data/lib/datadog/di/instrumenter.rb +48 -5
- data/lib/datadog/di/probe_notification_builder.rb +37 -42
- data/lib/datadog/di/probe_notifier_worker.rb +9 -1
- data/lib/datadog/di/serializer.rb +10 -2
- data/lib/datadog/di/transport/http/input.rb +10 -0
- data/lib/datadog/di/transport/input.rb +10 -2
- data/lib/datadog/di.rb +0 -6
- data/lib/datadog/kit/appsec/events/v2.rb +195 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +17 -8
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/info.rb +41 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +16 -1
- data/lib/datadog/profiling/component.rb +8 -9
- data/lib/datadog/profiling/exporter.rb +9 -3
- data/lib/datadog/profiling/ext.rb +0 -12
- data/lib/datadog/profiling/http_transport.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +2 -1
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +5 -5
- data/lib/datadog/profiling/tag_builder.rb +7 -37
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/profiling.rb +1 -0
- data/lib/datadog/single_step_instrument.rb +9 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -6
- data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +61 -40
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/tracing/span_event.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +22 -0
- data/lib/datadog/tracing/sync_writer.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +12 -4
- data/lib/datadog/tracing/tracer.rb +6 -2
- data/lib/datadog/version.rb +1 -1
- data/lib/datadog.rb +7 -0
- metadata +14 -10
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
- data/lib/datadog/appsec/processor.rb +0 -107
@@ -67,6 +67,7 @@ module Datadog
|
|
67
67
|
allocation_profiling_enabled: allocation_profiling_enabled,
|
68
68
|
allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled,
|
69
69
|
gvl_profiling_enabled: enable_gvl_profiling?(settings, logger),
|
70
|
+
sighandler_sampling_enabled: settings.profiling.advanced.sighandler_sampling_enabled,
|
70
71
|
)
|
71
72
|
|
72
73
|
internal_metadata = {
|
@@ -96,6 +97,7 @@ module Datadog
|
|
96
97
|
timeline_enabled: timeline_enabled,
|
97
98
|
waiting_for_gvl_threshold_ns: settings.profiling.advanced.waiting_for_gvl_threshold_ns,
|
98
99
|
otel_context_enabled: settings.profiling.advanced.preview_otel_context_enabled,
|
100
|
+
native_filenames_enabled: settings.profiling.advanced.native_filenames_enabled,
|
99
101
|
)
|
100
102
|
end
|
101
103
|
|
@@ -221,13 +223,14 @@ module Datadog
|
|
221
223
|
end
|
222
224
|
|
223
225
|
unless allocation_profiling_enabled
|
224
|
-
|
226
|
+
logger.warn(
|
227
|
+
"Heap profiling was requested but allocation profiling is not enabled. " \
|
228
|
+
"Heap profiling has been disabled."
|
229
|
+
)
|
230
|
+
return false
|
225
231
|
end
|
226
232
|
|
227
|
-
logger.
|
228
|
-
"Enabled experimental heap profiling: heap_sample_rate=#{heap_sample_rate}. This is experimental, not " \
|
229
|
-
"recommended, and will increase overhead!"
|
230
|
-
)
|
233
|
+
logger.debug("Enabled heap profiling: heap_sample_rate=#{heap_sample_rate}")
|
231
234
|
|
232
235
|
true
|
233
236
|
end
|
@@ -237,10 +240,6 @@ module Datadog
|
|
237
240
|
|
238
241
|
return false unless heap_profiling_enabled && heap_size_profiling_enabled
|
239
242
|
|
240
|
-
logger.warn(
|
241
|
-
"Enabled experimental heap size profiling. This is experimental, not recommended, and will increase overhead!"
|
242
|
-
)
|
243
|
-
|
244
243
|
true
|
245
244
|
end
|
246
245
|
|
@@ -26,7 +26,8 @@ module Datadog
|
|
26
26
|
:last_flush_finish_at,
|
27
27
|
:created_at,
|
28
28
|
:internal_metadata,
|
29
|
-
:info_json
|
29
|
+
:info_json,
|
30
|
+
:sequence_tracker
|
30
31
|
|
31
32
|
public
|
32
33
|
|
@@ -37,7 +38,8 @@ module Datadog
|
|
37
38
|
code_provenance_collector:,
|
38
39
|
internal_metadata:,
|
39
40
|
minimum_duration_seconds: PROFILE_DURATION_THRESHOLD_SECONDS,
|
40
|
-
time_provider: Time
|
41
|
+
time_provider: Time,
|
42
|
+
sequence_tracker: Datadog::Profiling::SequenceTracker
|
41
43
|
)
|
42
44
|
@pprof_recorder = pprof_recorder
|
43
45
|
@worker = worker
|
@@ -50,6 +52,7 @@ module Datadog
|
|
50
52
|
# NOTE: At the time of this comment collected info does not change over time so we'll hardcode
|
51
53
|
# it on startup to prevent serializing the same info on every flush.
|
52
54
|
@info_json = JSON.generate(info_collector.info).freeze
|
55
|
+
@sequence_tracker = sequence_tracker
|
53
56
|
end
|
54
57
|
|
55
58
|
def flush
|
@@ -73,7 +76,10 @@ module Datadog
|
|
73
76
|
encoded_profile: encoded_profile,
|
74
77
|
code_provenance_file_name: Datadog::Profiling::Ext::Transport::HTTP::CODE_PROVENANCE_FILENAME,
|
75
78
|
code_provenance_data: uncompressed_code_provenance,
|
76
|
-
tags_as_array: Datadog::Profiling::TagBuilder.call(
|
79
|
+
tags_as_array: Datadog::Profiling::TagBuilder.call(
|
80
|
+
settings: Datadog.configuration,
|
81
|
+
profile_seq: sequence_tracker.get_next,
|
82
|
+
).to_a,
|
77
83
|
internal_metadata: internal_metadata.merge(
|
78
84
|
{
|
79
85
|
worker_stats: worker_stats,
|
@@ -11,19 +11,7 @@ module Datadog
|
|
11
11
|
|
12
12
|
module Transport
|
13
13
|
module HTTP
|
14
|
-
FORM_FIELD_TAG_ENV = "env"
|
15
|
-
FORM_FIELD_TAG_HOST = "host"
|
16
|
-
FORM_FIELD_TAG_LANGUAGE = "language"
|
17
|
-
FORM_FIELD_TAG_PID = "process_id"
|
18
14
|
FORM_FIELD_TAG_PROFILER_VERSION = "profiler_version"
|
19
|
-
FORM_FIELD_TAG_RUNTIME = "runtime"
|
20
|
-
FORM_FIELD_TAG_RUNTIME_ENGINE = "runtime_engine"
|
21
|
-
FORM_FIELD_TAG_RUNTIME_ID = "runtime-id"
|
22
|
-
FORM_FIELD_TAG_RUNTIME_VERSION = "runtime_version"
|
23
|
-
FORM_FIELD_TAG_SERVICE = "service"
|
24
|
-
FORM_FIELD_TAG_VERSION = "version"
|
25
|
-
TAG_GIT_REPOSITORY_URL = "git.repository_url"
|
26
|
-
TAG_GIT_COMMIT_SHA = "git.commit.sha"
|
27
15
|
|
28
16
|
CODE_PROVENANCE_FILENAME = "code-provenance.json"
|
29
17
|
end
|
@@ -37,7 +37,7 @@ module Datadog
|
|
37
37
|
Datadog.logger.debug("Successfully reported profiling data")
|
38
38
|
true
|
39
39
|
else
|
40
|
-
Datadog.logger.
|
40
|
+
Datadog.logger.warn(
|
41
41
|
"Failed to report profiling data (#{config_without_api_key}): " \
|
42
42
|
"server returned unexpected HTTP #{result} status code"
|
43
43
|
)
|
@@ -47,7 +47,7 @@ module Datadog
|
|
47
47
|
false
|
48
48
|
end
|
49
49
|
else
|
50
|
-
Datadog.logger.
|
50
|
+
Datadog.logger.warn("Failed to report profiling data (#{config_without_api_key}): #{result}")
|
51
51
|
Datadog::Core::Telemetry::Logger.error("Failed to report profiling data")
|
52
52
|
false
|
53
53
|
end
|
@@ -50,6 +50,8 @@ module Datadog
|
|
50
50
|
"Detected issue with profiler (#{failed_component} component), stopping profiling. " \
|
51
51
|
"See previous log messages for details."
|
52
52
|
)
|
53
|
+
Datadog::Core::Telemetry::Logger
|
54
|
+
.error("Detected issue with profiler (#{failed_component} component), stopping profiling")
|
53
55
|
|
54
56
|
# We explicitly not stop the crash tracker in this situation, under the assumption that, if a component failed,
|
55
57
|
# we're operating in a degraded state and crash tracking may still be helpful.
|
@@ -68,6 +68,7 @@ module Datadog
|
|
68
68
|
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
69
69
|
)
|
70
70
|
on_failure_proc&.call
|
71
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "Profiling::Scheduler thread error")
|
71
72
|
raise
|
72
73
|
ensure
|
73
74
|
Datadog.logger.debug("#flush was interrupted or failed before it could complete") if interrupted
|
@@ -133,7 +134,7 @@ module Datadog
|
|
133
134
|
begin
|
134
135
|
transport.export(flush)
|
135
136
|
rescue => e
|
136
|
-
Datadog.logger.
|
137
|
+
Datadog.logger.warn(
|
137
138
|
"Unable to report profile. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
138
139
|
)
|
139
140
|
Datadog::Core::Telemetry::Logger.report(e, description: "Unable to report profile")
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../core/utils/forking'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Profiling
|
7
|
+
# Used to generate the `profile_seq` tag, which effectively counts how many profiles we've attempted to report
|
8
|
+
# from a given runtime-id.
|
9
|
+
#
|
10
|
+
# Note that the above implies a few things:
|
11
|
+
# 1. The sequence number only gets incremented when we decide to report a profile and create a `Flush` for it
|
12
|
+
# 2. The `SequenceTracker` must live across profiler reconfigurations and resets, since no matter how many
|
13
|
+
# profiler instances get created due to reconfiguration, the runtime-id is still the same, so the sequence number
|
14
|
+
# should be kept and not restarted from 0
|
15
|
+
# 3. The `SequenceTracker` must be reset after a fork, since the runtime-id will change, and we want to start
|
16
|
+
# counting from 0 again
|
17
|
+
#
|
18
|
+
# This is why this module is implemented as a singleton that we reuse, not as an instance that we recreate.
|
19
|
+
#
|
20
|
+
# Note that this module is not thread-safe, so it's up to the callers to make sure
|
21
|
+
# it's only used by a single thread at a time (which is what the `Profiling::Exporter`)
|
22
|
+
# is doing.
|
23
|
+
module SequenceTracker
|
24
|
+
class << self
|
25
|
+
include Core::Utils::Forking
|
26
|
+
|
27
|
+
def get_next
|
28
|
+
reset! unless defined?(@sequence_number)
|
29
|
+
after_fork! { reset! }
|
30
|
+
|
31
|
+
next_seq = @sequence_number
|
32
|
+
@sequence_number += 1
|
33
|
+
next_seq
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def reset!
|
39
|
+
@sequence_number = 0
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -23,7 +23,7 @@ module Datadog
|
|
23
23
|
# This isn't something we expect to happen normally, but because it would break the assumptions of the
|
24
24
|
# C-level mutexes (that there is a single serializer thread), we add it here as an extra safeguard against it
|
25
25
|
# accidentally happening.
|
26
|
-
@
|
26
|
+
@no_concurrent_serialize_mutex = Mutex.new
|
27
27
|
|
28
28
|
self.class._native_initialize(
|
29
29
|
self_instance: self,
|
@@ -60,7 +60,7 @@ module Datadog
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def serialize
|
63
|
-
status, result = @
|
63
|
+
status, result = @no_concurrent_serialize_mutex.synchronize { self.class._native_serialize(self) }
|
64
64
|
|
65
65
|
if status == :ok
|
66
66
|
start, finish, encoded_profile, profile_stats = result
|
@@ -71,15 +71,15 @@ module Datadog
|
|
71
71
|
else
|
72
72
|
error_message = result
|
73
73
|
|
74
|
-
Datadog.logger.
|
75
|
-
Datadog::Core::Telemetry::Logger.error("Failed to serialize profiling data")
|
74
|
+
Datadog.logger.warn("Failed to serialize profiling data: #{error_message}")
|
75
|
+
Datadog::Core::Telemetry::Logger.error("Failed to serialize profiling data (#{error_message})")
|
76
76
|
|
77
77
|
nil
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
def serialize!
|
82
|
-
status, result = @
|
82
|
+
status, result = @no_concurrent_serialize_mutex.synchronize { self.class._native_serialize(self) }
|
83
83
|
|
84
84
|
if status == :ok
|
85
85
|
_start, _finish, encoded_profile = result
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../core/tag_builder"
|
3
4
|
require_relative "../core/utils"
|
4
|
-
require_relative "../core/environment/git"
|
5
5
|
|
6
6
|
module Datadog
|
7
7
|
module Profiling
|
@@ -11,45 +11,15 @@ module Datadog
|
|
11
11
|
|
12
12
|
def self.call(
|
13
13
|
settings:,
|
14
|
-
# Unified service tagging
|
15
|
-
env: settings.env,
|
16
|
-
service: settings.service,
|
17
|
-
version: settings.version,
|
18
14
|
# Other metadata
|
19
|
-
|
20
|
-
|
21
|
-
pid: Process.pid.to_s,
|
22
|
-
profiler_version: Core::Environment::Identity.gem_datadog_version,
|
23
|
-
runtime_engine: Core::Environment::Identity.lang_engine,
|
24
|
-
runtime_id: Core::Environment::Identity.id,
|
25
|
-
runtime_version: Core::Environment::Identity.lang_version,
|
26
|
-
git_repository_url: Core::Environment::Git.git_repository_url,
|
27
|
-
git_commit_sha: Core::Environment::Git.git_commit_sha,
|
28
|
-
# User-provided tags
|
29
|
-
user_tags: settings.tags
|
15
|
+
profile_seq:,
|
16
|
+
profiler_version: Core::Environment::Identity.gem_datadog_version
|
30
17
|
)
|
31
|
-
|
32
|
-
# When changing or adding these, make sure they are kept in sync with
|
33
|
-
# https://docs.google.com/spreadsheets/d/1LOGMf4c4Avbtn36uZ2SWvhIGKRPLM1BoWkUP4JYj7hA/ (Datadog internal link)
|
34
|
-
FORM_FIELD_TAG_HOST => host,
|
35
|
-
FORM_FIELD_TAG_LANGUAGE => language,
|
36
|
-
FORM_FIELD_TAG_PID => pid,
|
18
|
+
hash = Core::TagBuilder.tags(settings).merge(
|
37
19
|
FORM_FIELD_TAG_PROFILER_VERSION => profiler_version,
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
FORM_FIELD_TAG_RUNTIME_VERSION => runtime_version,
|
42
|
-
}
|
43
|
-
tags[FORM_FIELD_TAG_ENV] = env if env
|
44
|
-
tags[FORM_FIELD_TAG_SERVICE] = service if service
|
45
|
-
tags[FORM_FIELD_TAG_VERSION] = version if version
|
46
|
-
tags[TAG_GIT_REPOSITORY_URL] = git_repository_url if git_repository_url
|
47
|
-
tags[TAG_GIT_COMMIT_SHA] = git_commit_sha if git_commit_sha
|
48
|
-
|
49
|
-
# Make sure everything is an utf-8 string, to avoid encoding issues in native code/further downstream
|
50
|
-
user_tags.merge(tags).map do |key, value|
|
51
|
-
[Datadog::Core::Utils.utf8_encode(key), Datadog::Core::Utils.utf8_encode(value)]
|
52
|
-
end.to_h
|
20
|
+
'profile_seq' => profile_seq.to_s,
|
21
|
+
)
|
22
|
+
Core::Utils.encode_tags(hash)
|
53
23
|
end
|
54
24
|
end
|
55
25
|
end
|
@@ -19,6 +19,7 @@ module Datadog
|
|
19
19
|
"Profiler extensions unavailable. Cause: #{e.class.name} #{e.message} " \
|
20
20
|
"Location: #{Array(e.backtrace).first}"
|
21
21
|
end
|
22
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "Profiler extensions unavailable")
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -33,6 +34,7 @@ module Datadog
|
|
33
34
|
"Error during post-fork hooks. Cause: #{e.class.name} #{e.message} " \
|
34
35
|
"Location: #{Array(e.backtrace).first}"
|
35
36
|
end
|
37
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "Error during post-fork hooks")
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
data/lib/datadog/profiling.rb
CHANGED
@@ -5,8 +5,17 @@
|
|
5
5
|
#
|
6
6
|
# This file's path is private. Do not reference this file.
|
7
7
|
#
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
# This module handles conditional loading of single step auto-instrumentation,
|
11
|
+
# which enables Datadog tracing and profiling features when available.
|
12
|
+
module SingleStepInstrument
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
8
16
|
begin
|
9
17
|
require_relative 'auto_instrument'
|
18
|
+
Datadog::SingleStepInstrument::LOADED = true
|
10
19
|
rescue StandardError, LoadError => e
|
11
20
|
warn "Single step instrumentation failed: #{e.class}:#{e.message}\n\tSource:\n\t#{Array(e.backtrace).join("\n\t")}"
|
12
21
|
end
|
@@ -68,6 +68,12 @@ module Datadog
|
|
68
68
|
|
69
69
|
span.set_tag(Ext::TAG_ROUTE_ACTION, payload.fetch(:action))
|
70
70
|
span.set_tag(Ext::TAG_ROUTE_CONTROLLER, payload.fetch(:controller))
|
71
|
+
if (runtime = payload[:view_runtime])
|
72
|
+
span.set_tag(Ext::TAG_VIEW_RUNTIME, runtime)
|
73
|
+
end
|
74
|
+
if (runtime = payload[:db_runtime])
|
75
|
+
span.set_tag(Ext::TAG_DB_RUNTIME, runtime)
|
76
|
+
end
|
71
77
|
|
72
78
|
exception = payload[:exception_object]
|
73
79
|
if exception.nil?
|
@@ -118,6 +124,15 @@ module Datadog
|
|
118
124
|
payload[:exception] = [e.class.name, e.message]
|
119
125
|
payload[:exception_object] = e
|
120
126
|
raise e
|
127
|
+
ensure
|
128
|
+
# Database and view runtime are available for controllers
|
129
|
+
# deriving from ActionController::Base.
|
130
|
+
# They are not defined on controllers deriving from
|
131
|
+
# ActionController::Metal, unless
|
132
|
+
# ActionController::Instrumentation is explicitly included
|
133
|
+
# into the controller class.
|
134
|
+
payload[:db_runtime] = db_runtime if respond_to?(:db_runtime)
|
135
|
+
payload[:view_runtime] = view_runtime if respond_to?(:view_runtime)
|
121
136
|
end
|
122
137
|
# rubocop:enable Lint/RescueException
|
123
138
|
ensure
|
@@ -9,9 +9,12 @@ module Datadog
|
|
9
9
|
module ActionDispatch
|
10
10
|
# Instrumentation for ActionDispatch components
|
11
11
|
module Instrumentation
|
12
|
+
SCRIPT_NAME_KEY = 'SCRIPT_NAME'
|
13
|
+
FORMAT_SUFFIX = '(.:format)'
|
14
|
+
|
12
15
|
module_function
|
13
16
|
|
14
|
-
def set_http_route_tags(route_spec,
|
17
|
+
def set_http_route_tags(route_spec, route_path)
|
15
18
|
return unless Tracing.enabled?
|
16
19
|
|
17
20
|
return unless route_spec
|
@@ -19,10 +22,10 @@ module Datadog
|
|
19
22
|
request_trace = Tracing.active_trace
|
20
23
|
return unless request_trace
|
21
24
|
|
22
|
-
request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, route_spec
|
25
|
+
request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, route_spec)
|
23
26
|
|
24
|
-
if
|
25
|
-
request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH,
|
27
|
+
if route_path && !route_path.empty?
|
28
|
+
request_trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, route_path)
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
@@ -40,16 +43,17 @@ module Datadog
|
|
40
43
|
# Instrumentation for ActionDispatch::Journey::Router for Rails versions older than 7.1
|
41
44
|
module Router
|
42
45
|
def find_routes(req)
|
46
|
+
# result is an array of [match, parameters, route] tuples
|
43
47
|
result = super
|
48
|
+
result.each do |_, _, route|
|
49
|
+
next unless Instrumentation.dispatcher_route?(route)
|
44
50
|
|
45
|
-
|
46
|
-
|
51
|
+
http_route = route.path.spec.to_s
|
52
|
+
http_route.delete_suffix!(FORMAT_SUFFIX)
|
47
53
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
break
|
52
|
-
end
|
54
|
+
Instrumentation.set_http_route_tags(http_route, req.env[SCRIPT_NAME_KEY])
|
55
|
+
|
56
|
+
break
|
53
57
|
end
|
54
58
|
|
55
59
|
result
|
@@ -62,7 +66,10 @@ module Datadog
|
|
62
66
|
def find_routes(req)
|
63
67
|
super do |match, parameters, route|
|
64
68
|
if Instrumentation.dispatcher_route?(route)
|
65
|
-
|
69
|
+
http_route = route.path.spec.to_s
|
70
|
+
http_route.delete_suffix!(FORMAT_SUFFIX)
|
71
|
+
|
72
|
+
Instrumentation.set_http_route_tags(http_route, req.env[SCRIPT_NAME_KEY])
|
66
73
|
end
|
67
74
|
|
68
75
|
yield [match, parameters, route]
|
@@ -45,9 +45,15 @@ module Datadog
|
|
45
45
|
'cache_write_multi.active_support' => { resource: Ext::RESOURCE_CACHE_MSET, multi_key: true }
|
46
46
|
}.freeze
|
47
47
|
|
48
|
-
def trace?(event,
|
48
|
+
def trace?(event, payload)
|
49
49
|
return false if !Tracing.enabled? || !configuration.enabled
|
50
50
|
|
51
|
+
if (cache_store = configuration[:cache_store])
|
52
|
+
store = cache_backend(payload[:store])
|
53
|
+
|
54
|
+
return false unless cache_store.include?(store)
|
55
|
+
end
|
56
|
+
|
51
57
|
# DEV-3.0: Backwards compatibility code for the 2.x gem series.
|
52
58
|
# DEV-3.0: See documentation at {Datadog::Tracing::Contrib::ActiveSupport::Cache::Instrumentation}
|
53
59
|
# DEV-3.0: for the complete information about this backwards compatibility code.
|
@@ -49,6 +49,19 @@ module Datadog
|
|
49
49
|
o.default true
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
# Specifies which cache stores to trace.
|
54
|
+
# Accepts a list, with the same format as `config.cache_store`
|
55
|
+
# (e.g. `memory_store`, `file_store`, or symbols like `:file_store`).
|
56
|
+
# Defaults to `nil`, which traces all cache stores.
|
57
|
+
# @see https://github.com/rails/rails/blob/b7520a13adda46c0cc5f3fb4a4c1726633af2bba/guides/source/caching_with_rails.md?plain=1#L576-L582
|
58
|
+
option :cache_store do |o|
|
59
|
+
o.type :array, nilable: true
|
60
|
+
o.default nil
|
61
|
+
o.after_set do |stores|
|
62
|
+
stores&.map!(&:to_s) # Convert symbols to strings to match the Rails configuration format
|
63
|
+
end
|
64
|
+
end
|
52
65
|
end
|
53
66
|
end
|
54
67
|
end
|
@@ -20,10 +20,12 @@ module Datadog
|
|
20
20
|
|
21
21
|
# patch applies our patch
|
22
22
|
def patch
|
23
|
+
# First check Lograge logger directly for when keep_original_rails_log option is used
|
24
|
+
used_logger = ::Lograge.logger || ::Lograge::LogSubscribers::ActionController.logger
|
25
|
+
|
23
26
|
# ActiveSupport::TaggedLogging is the default Rails logger since Rails 5
|
24
27
|
if defined?(::ActiveSupport::TaggedLogging::Formatter) &&
|
25
|
-
::
|
26
|
-
.logger&.formatter.is_a?(::ActiveSupport::TaggedLogging::Formatter)
|
28
|
+
used_logger&.formatter.is_a?(::ActiveSupport::TaggedLogging::Formatter)
|
27
29
|
Datadog.logger.warn(
|
28
30
|
'Lograge and ActiveSupport::TaggedLogging (the default Rails log formatter) are not compatible: ' \
|
29
31
|
'Lograge does not account for Rails log tags, creating polluted logs and breaking log formatting. ' \
|
@@ -45,16 +45,13 @@ module Datadog
|
|
45
45
|
span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
|
46
46
|
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_QUERY)
|
47
47
|
|
48
|
-
span
|
48
|
+
tag_database_instance(span, query_options[:database])
|
49
|
+
|
50
|
+
set_span_tags(span, query_options)
|
49
51
|
|
50
52
|
# Set analytics sample rate
|
51
53
|
Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
|
52
54
|
|
53
|
-
span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, query_options[:database])
|
54
|
-
span.set_tag(Ext::TAG_DB_NAME, query_options[:database])
|
55
|
-
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, query_options[:host])
|
56
|
-
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, query_options[:port])
|
57
|
-
|
58
55
|
Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
|
59
56
|
|
60
57
|
sql = inject_propagation(span, sql, trace_op)
|
@@ -91,6 +88,19 @@ module Datadog
|
|
91
88
|
def analytics_sample_rate
|
92
89
|
datadog_configuration[:analytics_sample_rate]
|
93
90
|
end
|
91
|
+
|
92
|
+
def tag_database_instance(span, database)
|
93
|
+
return if database.nil? || database.empty?
|
94
|
+
|
95
|
+
span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, database)
|
96
|
+
span.set_tag(Ext::TAG_DB_NAME, database)
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_span_tags(span, query_options)
|
100
|
+
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, query_options[:host])
|
101
|
+
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, query_options[:port])
|
102
|
+
span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, query_options[:host])
|
103
|
+
end
|
94
104
|
end
|
95
105
|
end
|
96
106
|
end
|
@@ -86,7 +86,10 @@ module Datadog
|
|
86
86
|
|
87
87
|
# Instruments the `bin/rails runner` command.
|
88
88
|
def patch_rails_runner
|
89
|
-
|
89
|
+
# The `RunnerCommand` class is only available in Rails 5.1 and later.
|
90
|
+
if defined?(::Rails::Command::RunnerCommand) && Integration.version >= Gem::Version.new('5.1')
|
91
|
+
::Rails::Command::RunnerCommand.prepend(Runner)
|
92
|
+
end
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|