datadog 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|