datadog 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -2
- data/ext/datadog_profiling_loader/extconf.rb +15 -15
- data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +113 -43
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +49 -37
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +65 -60
- data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
- data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/helpers.h +6 -17
- data/ext/datadog_profiling_native_extension/http_transport.c +3 -3
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -172
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
- data/ext/datadog_profiling_native_extension/profiling.c +0 -2
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
- data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
- data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +19 -6
- data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
- data/ext/libdatadog_api/extconf.rb +108 -0
- data/ext/libdatadog_api/macos_development.md +26 -0
- data/ext/libdatadog_extconf_helpers.rb +130 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +14 -12
- data/lib/datadog/core/configuration/settings.rb +54 -7
- data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
- data/lib/datadog/core/crashtracking/component.rb +111 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/telemetry/component.rb +49 -2
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +32 -1
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
- data/lib/datadog/core/telemetry/http/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/transport.rb +38 -9
- data/lib/datadog/core/telemetry/logging.rb +35 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +3 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
- data/lib/datadog/profiling/component.rb +69 -91
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +8 -6
- data/lib/datadog/profiling/load_native_extension.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +5 -8
- data/lib/datadog/profiling/scheduler.rb +31 -25
- data/lib/datadog/profiling/tag_builder.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +5 -5
- data/lib/datadog/profiling/tasks/setup.rb +16 -35
- data/lib/datadog/profiling.rb +4 -5
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -0
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +1 -1
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +4 -1
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/span.rb +9 -2
- data/lib/datadog/tracing/span_event.rb +41 -0
- data/lib/datadog/tracing/span_operation.rb +6 -2
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/version.rb +1 -1
- metadata +28 -10
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -27,7 +27,7 @@ module Datadog
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
if RUBY_VERSION.start_with?(
|
30
|
+
if RUBY_VERSION.start_with?("2.")
|
31
31
|
# Monkey patches for Dir.singleton_class (Ruby 2 version). See DirMonkeyPatches above for more details.
|
32
32
|
module DirClassMonkeyPatches
|
33
33
|
def [](*args, &block)
|
@@ -260,7 +260,7 @@ module Datadog
|
|
260
260
|
end
|
261
261
|
end
|
262
262
|
|
263
|
-
if RUBY_VERSION.start_with?(
|
263
|
+
if RUBY_VERSION.start_with?("2.")
|
264
264
|
# Monkey patches for Dir (Ruby 2 version). See DirMonkeyPatches above for more details.
|
265
265
|
module DirInstanceMonkeyPatches
|
266
266
|
# See note on methods that yield above.
|
@@ -286,7 +286,7 @@ module Datadog
|
|
286
286
|
end
|
287
287
|
end
|
288
288
|
|
289
|
-
unless RUBY_VERSION.start_with?(
|
289
|
+
unless RUBY_VERSION.start_with?("2.5.") # This is Ruby 2.6+
|
290
290
|
# See note on methods that yield above.
|
291
291
|
def each_child(*args, &block)
|
292
292
|
if block
|
@@ -3,31 +3,31 @@
|
|
3
3
|
module Datadog
|
4
4
|
module Profiling
|
5
5
|
module Ext
|
6
|
-
ENV_ENABLED =
|
7
|
-
ENV_UPLOAD_TIMEOUT =
|
8
|
-
ENV_MAX_FRAMES =
|
9
|
-
ENV_AGENTLESS =
|
10
|
-
ENV_ENDPOINT_COLLECTION_ENABLED =
|
6
|
+
ENV_ENABLED = "DD_PROFILING_ENABLED"
|
7
|
+
ENV_UPLOAD_TIMEOUT = "DD_PROFILING_UPLOAD_TIMEOUT"
|
8
|
+
ENV_MAX_FRAMES = "DD_PROFILING_MAX_FRAMES"
|
9
|
+
ENV_AGENTLESS = "DD_PROFILING_AGENTLESS"
|
10
|
+
ENV_ENDPOINT_COLLECTION_ENABLED = "DD_PROFILING_ENDPOINT_COLLECTION_ENABLED"
|
11
11
|
|
12
12
|
module Transport
|
13
13
|
module HTTP
|
14
|
-
FORM_FIELD_TAG_ENV =
|
15
|
-
FORM_FIELD_TAG_HOST =
|
16
|
-
FORM_FIELD_TAG_LANGUAGE =
|
17
|
-
FORM_FIELD_TAG_PID =
|
18
|
-
FORM_FIELD_TAG_PROFILER_VERSION =
|
19
|
-
FORM_FIELD_TAG_RUNTIME =
|
20
|
-
FORM_FIELD_TAG_RUNTIME_ENGINE =
|
21
|
-
FORM_FIELD_TAG_RUNTIME_ID =
|
22
|
-
FORM_FIELD_TAG_RUNTIME_PLATFORM =
|
23
|
-
FORM_FIELD_TAG_RUNTIME_VERSION =
|
24
|
-
FORM_FIELD_TAG_SERVICE =
|
25
|
-
FORM_FIELD_TAG_VERSION =
|
26
|
-
TAG_GIT_REPOSITORY_URL =
|
27
|
-
TAG_GIT_COMMIT_SHA =
|
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
|
+
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_PLATFORM = "runtime_platform"
|
23
|
+
FORM_FIELD_TAG_RUNTIME_VERSION = "runtime_version"
|
24
|
+
FORM_FIELD_TAG_SERVICE = "service"
|
25
|
+
FORM_FIELD_TAG_VERSION = "version"
|
26
|
+
TAG_GIT_REPOSITORY_URL = "git.repository_url"
|
27
|
+
TAG_GIT_COMMIT_SHA = "git.commit.sha"
|
28
28
|
|
29
|
-
PPROF_DEFAULT_FILENAME =
|
30
|
-
CODE_PROVENANCE_FILENAME =
|
29
|
+
PPROF_DEFAULT_FILENAME = "rubyprofile.pprof"
|
30
|
+
CODE_PROVENANCE_FILENAME = "code-provenance.json"
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "../core/transport/ext"
|
4
4
|
|
5
5
|
module Datadog
|
6
6
|
module Profiling
|
@@ -53,7 +53,7 @@ module Datadog
|
|
53
53
|
|
54
54
|
if status == :ok
|
55
55
|
if (200..299).cover?(result)
|
56
|
-
Datadog.logger.debug(
|
56
|
+
Datadog.logger.debug("Successfully reported profiling data")
|
57
57
|
true
|
58
58
|
else
|
59
59
|
Datadog.logger.error(
|
@@ -73,7 +73,7 @@ module Datadog
|
|
73
73
|
def base_url_from(agent_settings)
|
74
74
|
case agent_settings.adapter
|
75
75
|
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
76
|
-
"#{agent_settings.ssl ?
|
76
|
+
"#{agent_settings.ssl ? "https" : "http"}://#{agent_settings.hostname}:#{agent_settings.port}/"
|
77
77
|
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
|
78
78
|
"unix://#{agent_settings.uds_path}"
|
79
79
|
else
|
@@ -82,12 +82,14 @@ module Datadog
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def validate_agent_settings(agent_settings)
|
85
|
-
supported_adapters = [
|
86
|
-
|
85
|
+
supported_adapters = [
|
86
|
+
Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER,
|
87
|
+
Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
88
|
+
]
|
87
89
|
unless supported_adapters.include?(agent_settings.adapter)
|
88
90
|
raise ArgumentError,
|
89
91
|
"Unsupported transport configuration for profiling: Adapter #{agent_settings.adapter} " \
|
90
|
-
|
92
|
+
" is not supported"
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
@@ -15,26 +15,26 @@ begin
|
|
15
15
|
require "datadog_profiling_loader.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
|
16
16
|
rescue LoadError => e
|
17
17
|
raise LoadError,
|
18
|
-
|
18
|
+
"Failed to load the profiling loader extension. To fix this, please remove and then reinstall datadog " \
|
19
19
|
"(Details: #{e.message})"
|
20
20
|
end
|
21
21
|
|
22
22
|
extension_name = "datadog_profiling_native_extension.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
|
23
|
-
file_name = "#{extension_name}.#{RbConfig::CONFIG[
|
23
|
+
file_name = "#{extension_name}.#{RbConfig::CONFIG["DLEXT"]}"
|
24
24
|
full_file_path = "#{__dir__}/../../#{file_name}"
|
25
25
|
|
26
26
|
unless File.exist?(full_file_path)
|
27
|
-
extension_dir = Gem.loaded_specs[
|
27
|
+
extension_dir = Gem.loaded_specs["datadog"].extension_dir
|
28
28
|
candidate_path = "#{extension_dir}/#{file_name}"
|
29
29
|
if File.exist?(candidate_path)
|
30
30
|
full_file_path = candidate_path
|
31
|
-
else
|
31
|
+
else
|
32
32
|
# We found none of the files. This is unexpected. Let's go ahead anyway, the error is going to be reported further
|
33
33
|
# down anyway.
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
init_function_name = "Init_#{extension_name.split(
|
37
|
+
init_function_name = "Init_#{extension_name.split(".").first}"
|
38
38
|
|
39
39
|
status, result = Datadog::Profiling::Loader._native_load(full_file_path, init_function_name)
|
40
40
|
|
@@ -8,34 +8,30 @@ module Datadog
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
attr_reader :worker, :scheduler
|
11
|
+
attr_reader :worker, :scheduler
|
12
12
|
|
13
13
|
public
|
14
14
|
|
15
|
-
def initialize(worker:, scheduler
|
15
|
+
def initialize(worker:, scheduler:)
|
16
16
|
@worker = worker
|
17
17
|
@scheduler = scheduler
|
18
|
-
@optional_crashtracker = optional_crashtracker
|
19
18
|
end
|
20
19
|
|
21
20
|
def start
|
22
21
|
after_fork! do
|
23
|
-
optional_crashtracker.reset_after_fork if optional_crashtracker
|
24
22
|
worker.reset_after_fork
|
25
23
|
scheduler.reset_after_fork
|
26
24
|
end
|
27
25
|
|
28
|
-
optional_crashtracker.start if optional_crashtracker
|
29
26
|
worker.start(on_failure_proc: proc { component_failed(:worker) })
|
30
27
|
scheduler.start(on_failure_proc: proc { component_failed(:scheduler) })
|
31
28
|
end
|
32
29
|
|
33
30
|
def shutdown!
|
34
|
-
Datadog.logger.debug(
|
31
|
+
Datadog.logger.debug("Shutting down profiler")
|
35
32
|
|
36
33
|
stop_worker
|
37
34
|
stop_scheduler
|
38
|
-
optional_crashtracker.stop if optional_crashtracker
|
39
35
|
end
|
40
36
|
|
41
37
|
private
|
@@ -52,13 +48,14 @@ module Datadog
|
|
52
48
|
def component_failed(failed_component)
|
53
49
|
Datadog.logger.warn(
|
54
50
|
"Detected issue with profiler (#{failed_component} component), stopping profiling. " \
|
55
|
-
|
51
|
+
"See previous log messages for details."
|
56
52
|
)
|
57
53
|
|
58
54
|
# We explicitly not stop the crash tracker in this situation, under the assumption that, if a component failed,
|
59
55
|
# we're operating in a degraded state and crash tracking may still be helpful.
|
60
56
|
|
61
57
|
if failed_component == :worker
|
58
|
+
scheduler.mark_profiler_failed
|
62
59
|
stop_scheduler
|
63
60
|
elsif failed_component == :scheduler
|
64
61
|
stop_worker
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "../core/utils/time"
|
4
4
|
|
5
|
-
require_relative
|
6
|
-
require_relative
|
5
|
+
require_relative "../core/worker"
|
6
|
+
require_relative "../core/workers/polling"
|
7
7
|
|
8
8
|
module Datadog
|
9
9
|
module Profiling
|
@@ -22,7 +22,8 @@ module Datadog
|
|
22
22
|
|
23
23
|
attr_reader \
|
24
24
|
:exporter,
|
25
|
-
:transport
|
25
|
+
:transport,
|
26
|
+
:profiler_failed
|
26
27
|
|
27
28
|
public
|
28
29
|
|
@@ -34,6 +35,7 @@ module Datadog
|
|
34
35
|
)
|
35
36
|
@exporter = exporter
|
36
37
|
@transport = transport
|
38
|
+
@profiler_failed = false
|
37
39
|
|
38
40
|
# Workers::Async::Thread settings
|
39
41
|
self.fork_policy = fork_policy
|
@@ -50,25 +52,23 @@ module Datadog
|
|
50
52
|
end
|
51
53
|
|
52
54
|
def perform(on_failure_proc)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
Datadog.logger.debug('#flush was interrupted or failed before it could complete') if interrupted
|
71
|
-
end
|
55
|
+
# A profiling flush may be called while the VM is shutting down, to report the last profile. When we do so,
|
56
|
+
# we impose a strict timeout. This means this last profile may or may not be sent, depending on if the flush can
|
57
|
+
# successfully finish in the strict timeout.
|
58
|
+
# This can be somewhat confusing (why did it not get reported?), so let's at least log what happened.
|
59
|
+
interrupted = true
|
60
|
+
|
61
|
+
flush_and_wait
|
62
|
+
interrupted = false
|
63
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
64
|
+
Datadog.logger.warn(
|
65
|
+
"Profiling::Scheduler thread error. " \
|
66
|
+
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
67
|
+
)
|
68
|
+
on_failure_proc&.call
|
69
|
+
raise
|
70
|
+
ensure
|
71
|
+
Datadog.logger.debug("#flush was interrupted or failed before it could complete") if interrupted
|
72
72
|
end
|
73
73
|
|
74
74
|
# Configure Workers::IntervalLoop to not report immediately when scheduler starts
|
@@ -80,8 +80,14 @@ module Datadog
|
|
80
80
|
true
|
81
81
|
end
|
82
82
|
|
83
|
+
# This is called by the Profiler class whenever an issue happened in the profiler. This makes sure that even
|
84
|
+
# if there is data to be flushed, we don't try to flush it.
|
85
|
+
def mark_profiler_failed
|
86
|
+
@profiler_failed = true
|
87
|
+
end
|
88
|
+
|
83
89
|
def work_pending?
|
84
|
-
exporter.can_flush?
|
90
|
+
!profiler_failed && exporter.can_flush?
|
85
91
|
end
|
86
92
|
|
87
93
|
def reset_after_fork
|
@@ -124,7 +130,7 @@ module Datadog
|
|
124
130
|
|
125
131
|
begin
|
126
132
|
transport.export(flush)
|
127
|
-
rescue
|
133
|
+
rescue => e
|
128
134
|
Datadog.logger.error(
|
129
135
|
"Unable to report profile. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
130
136
|
)
|
@@ -18,16 +18,16 @@ module Datadog
|
|
18
18
|
|
19
19
|
def rubyopts
|
20
20
|
[
|
21
|
-
|
21
|
+
"-rdatadog/profiling/preload"
|
22
22
|
]
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
27
|
def set_rubyopt!
|
28
|
-
existing_rubyopt = ENV[
|
28
|
+
existing_rubyopt = ENV["RUBYOPT"]
|
29
29
|
|
30
|
-
ENV[
|
30
|
+
ENV["RUBYOPT"] = existing_rubyopt ? "#{existing_rubyopt} #{rubyopts.join(" ")}" : rubyopts.join(" ")
|
31
31
|
end
|
32
32
|
|
33
33
|
# If there's an error here, rather than throwing a cryptic stack trace, let's instead have clearer messages, and
|
@@ -38,10 +38,10 @@ module Datadog
|
|
38
38
|
def exec_with_error_handling(args)
|
39
39
|
Kernel.exec(*args)
|
40
40
|
rescue Errno::ENOENT => e
|
41
|
-
Kernel.warn "ddprofrb exec failed: #{e.class.name} #{e.message} (command was '#{args.join(
|
41
|
+
Kernel.warn "ddprofrb exec failed: #{e.class.name} #{e.message} (command was '#{args.join(" ")}')"
|
42
42
|
Kernel.exit 127
|
43
43
|
rescue Errno::EACCES, Errno::ENOEXEC => e
|
44
|
-
Kernel.warn "ddprofrb exec failed: #{e.class.name} #{e.message} (command was '#{args.join(
|
44
|
+
Kernel.warn "ddprofrb exec failed: #{e.class.name} #{e.message} (command was '#{args.join(" ")}')"
|
45
45
|
Kernel.exit 126
|
46
46
|
end
|
47
47
|
end
|
@@ -1,56 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "../../core/utils/only_once"
|
4
|
+
require_relative "../../core/utils/at_fork_monkey_patch"
|
5
5
|
|
6
6
|
module Datadog
|
7
7
|
module Profiling
|
8
8
|
module Tasks
|
9
|
-
# Takes care of
|
9
|
+
# Takes care of restarting the profiler when the process forks
|
10
10
|
class Setup
|
11
11
|
ACTIVATE_EXTENSIONS_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
12
12
|
|
13
13
|
def run
|
14
14
|
ACTIVATE_EXTENSIONS_ONLY_ONCE.run do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
"Location: #{Array(e.backtrace).first}"
|
22
|
-
end
|
15
|
+
Datadog::Core::Utils::AtForkMonkeyPatch.apply!
|
16
|
+
setup_at_fork_hooks
|
17
|
+
rescue StandardError, ScriptError => e
|
18
|
+
Datadog.logger.warn do
|
19
|
+
"Profiler extensions unavailable. Cause: #{e.class.name} #{e.message} " \
|
20
|
+
"Location: #{Array(e.backtrace).first}"
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
25
|
private
|
28
26
|
|
29
|
-
def activate_forking_extensions
|
30
|
-
if Ext::Forking.supported?
|
31
|
-
Ext::Forking.apply!
|
32
|
-
elsif Datadog.configuration.profiling.enabled
|
33
|
-
Datadog.logger.debug('Profiler forking extensions skipped; forking not supported.')
|
34
|
-
end
|
35
|
-
rescue StandardError, ScriptError => e
|
36
|
-
Datadog.logger.warn do
|
37
|
-
"Profiler forking extensions unavailable. Cause: #{e.class.name} #{e.message} " \
|
38
|
-
"Location: #{Array(e.backtrace).first}"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
27
|
def setup_at_fork_hooks
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
"Error during post-fork hooks. Cause: #{e.class.name} #{e.message} " \
|
51
|
-
"Location: #{Array(e.backtrace).first}"
|
52
|
-
end
|
53
|
-
end
|
28
|
+
Datadog::Core::Utils::AtForkMonkeyPatch.at_fork(:child) do
|
29
|
+
# Restart profiler, if enabled
|
30
|
+
Profiling.start_if_enabled
|
31
|
+
rescue => e
|
32
|
+
Datadog.logger.warn do
|
33
|
+
"Error during post-fork hooks. Cause: #{e.class.name} #{e.message} " \
|
34
|
+
"Location: #{Array(e.backtrace).first}"
|
54
35
|
end
|
55
36
|
end
|
56
37
|
end
|
data/lib/datadog/profiling.rb
CHANGED
@@ -30,7 +30,7 @@ module Datadog
|
|
30
30
|
profiler = Datadog.send(:components).profiler
|
31
31
|
# ...but we still try to start it BECAUSE if the process forks, the profiler will exist but may
|
32
32
|
# not yet have been started in the fork
|
33
|
-
profiler
|
33
|
+
profiler&.start
|
34
34
|
!!profiler
|
35
35
|
end
|
36
36
|
|
@@ -47,6 +47,7 @@ module Datadog
|
|
47
47
|
# (This is similar to some OS-based time representations.)
|
48
48
|
#
|
49
49
|
# Note 2: All fibers in the same thread will share the same counter values.
|
50
|
+
# Note 3: This counter is not accurate when using the M:N scheduler.
|
50
51
|
#
|
51
52
|
# Only available when the profiler is running, and allocation-related features are not disabled via configuration.
|
52
53
|
#
|
@@ -62,7 +63,7 @@ module Datadog
|
|
62
63
|
def self.enabled?
|
63
64
|
profiler = Datadog.send(:components).profiler
|
64
65
|
# Use .send(...) to avoid exposing the attr_reader as an API to the outside
|
65
|
-
!!
|
66
|
+
!!profiler&.send(:scheduler)&.running?
|
66
67
|
end
|
67
68
|
|
68
69
|
def self.wait_until_running(timeout_seconds: 5)
|
@@ -97,7 +98,7 @@ module Datadog
|
|
97
98
|
|
98
99
|
contents = file_api.read(skipped_reason_file).strip
|
99
100
|
contents unless contents.empty?
|
100
|
-
rescue
|
101
|
+
rescue
|
101
102
|
# Do nothing
|
102
103
|
end
|
103
104
|
end
|
@@ -135,7 +136,6 @@ module Datadog
|
|
135
136
|
private_class_method def self.load_profiling
|
136
137
|
return false unless supported?
|
137
138
|
|
138
|
-
require_relative 'profiling/ext/forking'
|
139
139
|
require_relative 'profiling/ext/dir_monkey_patches'
|
140
140
|
require_relative 'profiling/collectors/info'
|
141
141
|
require_relative 'profiling/collectors/code_provenance'
|
@@ -144,7 +144,6 @@ module Datadog
|
|
144
144
|
require_relative 'profiling/collectors/idle_sampling_helper'
|
145
145
|
require_relative 'profiling/collectors/stack'
|
146
146
|
require_relative 'profiling/collectors/thread_context'
|
147
|
-
require_relative 'profiling/crashtracker'
|
148
147
|
require_relative 'profiling/stack_recorder'
|
149
148
|
require_relative 'profiling/exporter'
|
150
149
|
require_relative 'profiling/flush'
|
@@ -62,6 +62,7 @@ module Datadog
|
|
62
62
|
cached = payload[:cached] || (payload[:name] == PAYLOAD_CACHE)
|
63
63
|
|
64
64
|
span.set_tag(Ext::TAG_DB_VENDOR, adapter_name)
|
65
|
+
span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, config[:database])
|
65
66
|
span.set_tag(Ext::TAG_DB_NAME, config[:database])
|
66
67
|
span.set_tag(Ext::TAG_DB_CACHED, cached) if cached
|
67
68
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, config[:host]) if config[:host]
|
@@ -7,7 +7,21 @@ module Datadog
|
|
7
7
|
module Ext
|
8
8
|
# @public_api
|
9
9
|
module DB
|
10
|
+
# Name of the database. This is *not* the database hostname.
|
11
|
+
#
|
12
|
+
# For databases which support such a concept, the default schema/database/namespace
|
13
|
+
# as configured in the connection string.
|
14
|
+
#
|
15
|
+
# If the tracer is already tracking changes to the default schema/database throughout the lifetime of
|
16
|
+
# the session (i.e. the client executes USE {NEW_SCHEMA} and now the default schema has changed from what
|
17
|
+
# was set upon connection initialization), then ideally this attribute reflects the “current” value.
|
18
|
+
# If the tracer is not already tracking changes then just leaving it to the default value set upon
|
19
|
+
# initialization is OK.
|
20
|
+
#
|
21
|
+
# This is the equivalent of OTel’s `db.namespace`
|
22
|
+
# @see https://opentelemetry.io/docs/specs/semconv/database/database-spans/#common-attributes
|
10
23
|
TAG_INSTANCE = 'db.instance'
|
24
|
+
|
11
25
|
TAG_USER = 'db.user'
|
12
26
|
TAG_SYSTEM = 'db.system'
|
13
27
|
TAG_STATEMENT = 'db.statement'
|
@@ -1,5 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
if Gem.loaded_specs['graphql'] && Gem.loaded_specs['graphql'].version >= Gem::Version.new('2.0.19')
|
4
|
+
require_relative 'unified_trace'
|
5
|
+
end
|
6
|
+
|
3
7
|
module Datadog
|
4
8
|
module Tracing
|
5
9
|
module Contrib
|
@@ -9,7 +13,6 @@ module Datadog
|
|
9
13
|
module_function
|
10
14
|
|
11
15
|
def patch!(schemas, options)
|
12
|
-
require_relative 'unified_trace'
|
13
16
|
if schemas.empty?
|
14
17
|
::GraphQL::Schema.trace_with(UnifiedTrace, **options)
|
15
18
|
else
|
@@ -20,6 +20,22 @@ module Datadog
|
|
20
20
|
|
21
21
|
# patch applies our patch
|
22
22
|
def patch
|
23
|
+
# ActiveSupport::TaggedLogging is the default Rails logger since Rails 5
|
24
|
+
if defined?(::ActiveSupport::TaggedLogging::Formatter) &&
|
25
|
+
::Lograge::LogSubscribers::ActionController
|
26
|
+
.logger&.formatter.is_a?(::ActiveSupport::TaggedLogging::Formatter)
|
27
|
+
|
28
|
+
Datadog.logger.error(
|
29
|
+
'Lograge and ActiveSupport::TaggedLogging (the default Rails log formatter) are not compatible: ' \
|
30
|
+
'Lograge does not account for Rails log tags, creating polluted logs and breaking log formatting. ' \
|
31
|
+
'Traces and Logs correlation may not work. ' \
|
32
|
+
'Either: 1. Disable tagged logging in your Rails configuration ' \
|
33
|
+
'`config.logger = ActiveSupport::Logger.new(STDOUT); ' \
|
34
|
+
'config.active_job.logger = ActiveSupport::Logger.new(STDOUT)` ' \
|
35
|
+
'or 2. Use the `semantic_logger` gem instead of `lograge`.'
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
23
39
|
::Lograge::LogSubscribers::Base.include(Instrumentation)
|
24
40
|
end
|
25
41
|
end
|
@@ -48,6 +48,11 @@ module Datadog
|
|
48
48
|
o.default Contrib::Propagation::SqlComment::Ext::DISABLED
|
49
49
|
end
|
50
50
|
|
51
|
+
option :append_comment do |o|
|
52
|
+
o.type :bool
|
53
|
+
o.default false
|
54
|
+
end
|
55
|
+
|
51
56
|
option :peer_service do |o|
|
52
57
|
o.type :string, nilable: true
|
53
58
|
o.env Ext::ENV_PEER_SERVICE
|
@@ -50,21 +50,14 @@ module Datadog
|
|
50
50
|
# Set analytics sample rate
|
51
51
|
Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
|
52
52
|
|
53
|
+
span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, query_options[:database])
|
53
54
|
span.set_tag(Ext::TAG_DB_NAME, query_options[:database])
|
54
55
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, query_options[:host])
|
55
56
|
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, query_options[:port])
|
56
57
|
|
57
58
|
Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
Contrib::Propagation::SqlComment.annotate!(span, propagation_mode)
|
62
|
-
sql = Contrib::Propagation::SqlComment.prepend_comment(
|
63
|
-
sql,
|
64
|
-
span,
|
65
|
-
trace_op,
|
66
|
-
propagation_mode
|
67
|
-
)
|
60
|
+
sql = inject_propagation(span, sql, trace_op)
|
68
61
|
|
69
62
|
super(sql, options)
|
70
63
|
end
|
@@ -72,6 +65,21 @@ module Datadog
|
|
72
65
|
|
73
66
|
private
|
74
67
|
|
68
|
+
def inject_propagation(span, sql, trace_op)
|
69
|
+
propagation_mode = Contrib::Propagation::SqlComment::Mode.new(
|
70
|
+
datadog_configuration[:comment_propagation],
|
71
|
+
datadog_configuration[:append_comment]
|
72
|
+
)
|
73
|
+
|
74
|
+
Contrib::Propagation::SqlComment.annotate!(span, propagation_mode)
|
75
|
+
Contrib::Propagation::SqlComment.prepend_comment(
|
76
|
+
sql,
|
77
|
+
span,
|
78
|
+
trace_op,
|
79
|
+
propagation_mode
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
75
83
|
def datadog_configuration
|
76
84
|
Datadog.configuration.tracing[:mysql2]
|
77
85
|
end
|
@@ -83,10 +91,6 @@ module Datadog
|
|
83
91
|
def analytics_sample_rate
|
84
92
|
datadog_configuration[:analytics_sample_rate]
|
85
93
|
end
|
86
|
-
|
87
|
-
def comment_propagation
|
88
|
-
datadog_configuration[:comment_propagation]
|
89
|
-
end
|
90
94
|
end
|
91
95
|
end
|
92
96
|
end
|