ddtrace 1.20.0 → 1.22.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 +115 -1
- data/LICENSE-3rdparty.csv +1 -1
- data/bin/ddprofrb +15 -0
- data/bin/ddtracerb +3 -1
- data/ext/{ddtrace_profiling_loader/ddtrace_profiling_loader.c → datadog_profiling_loader/datadog_profiling_loader.c} +2 -2
- data/ext/{ddtrace_profiling_loader → datadog_profiling_loader}/extconf.rb +3 -3
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_cpu_and_wall_time_worker.c +238 -61
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_discrete_dynamic_sampler.c +145 -72
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_discrete_dynamic_sampler.h +17 -5
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.c +97 -4
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/extconf.rb +2 -2
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/heap_recorder.c +45 -3
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/heap_recorder.h +7 -1
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/http_transport.c +15 -19
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/native_extension_helpers.rb +4 -4
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.c +14 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.h +4 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/profiling.c +1 -1
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.c +10 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.h +2 -0
- data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.c +7 -9
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -13
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/components.rb +7 -6
- data/lib/datadog/core/configuration/option.rb +8 -6
- data/lib/datadog/core/configuration/settings.rb +130 -63
- data/lib/datadog/core/configuration.rb +20 -4
- data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
- data/lib/datadog/core/environment/git.rb +25 -0
- data/lib/datadog/core/environment/identity.rb +18 -48
- data/lib/datadog/core/environment/platform.rb +7 -1
- data/lib/datadog/core/git/ext.rb +2 -23
- data/lib/datadog/core/remote/client/capabilities.rb +1 -1
- data/lib/datadog/core/remote/negotiation.rb +2 -2
- data/lib/datadog/core/remote/transport/http/config.rb +1 -1
- data/lib/datadog/core/remote/worker.rb +7 -4
- data/lib/datadog/core/telemetry/client.rb +18 -10
- data/lib/datadog/core/telemetry/emitter.rb +9 -13
- data/lib/datadog/core/telemetry/event.rb +247 -57
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/heartbeat.rb +1 -3
- data/lib/datadog/core/telemetry/http/ext.rb +4 -1
- data/lib/datadog/core/telemetry/http/transport.rb +9 -4
- data/lib/datadog/core/telemetry/request.rb +59 -0
- data/lib/datadog/core/transport/ext.rb +2 -0
- data/lib/datadog/core/utils/url.rb +25 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +10 -4
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +31 -0
- data/lib/datadog/profiling/collectors/info.rb +101 -0
- data/lib/datadog/profiling/component.rb +34 -28
- data/lib/datadog/profiling/exporter.rb +19 -5
- data/lib/datadog/profiling/ext.rb +2 -0
- data/lib/datadog/profiling/flush.rb +6 -3
- data/lib/datadog/profiling/http_transport.rb +5 -1
- data/lib/datadog/profiling/load_native_extension.rb +19 -6
- data/lib/datadog/profiling/native_extension.rb +1 -1
- data/lib/datadog/profiling/tag_builder.rb +5 -0
- data/lib/datadog/profiling/tasks/exec.rb +3 -3
- data/lib/datadog/profiling/tasks/help.rb +3 -3
- data/lib/datadog/profiling.rb +13 -2
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +11 -4
- data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +11 -1
- data/lib/datadog/tracing/contrib/configurable.rb +1 -1
- data/lib/datadog/tracing/contrib/extensions.rb +6 -2
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +11 -4
- data/lib/datadog/tracing/sampling/matcher.rb +23 -3
- data/lib/datadog/tracing/sampling/rule.rb +7 -2
- data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
- data/lib/datadog/tracing/trace_operation.rb +1 -2
- data/lib/datadog/tracing/transport/http.rb +1 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +31 -0
- data/lib/ddtrace/version.rb +1 -1
- metadata +55 -62
- data/ext/ddtrace_profiling_native_extension/pid_controller.c +0 -57
- data/ext/ddtrace_profiling_native_extension/pid_controller.h +0 -45
- data/lib/datadog/core/telemetry/collector.rb +0 -250
- data/lib/datadog/core/telemetry/v1/app_event.rb +0 -59
- data/lib/datadog/core/telemetry/v1/application.rb +0 -92
- data/lib/datadog/core/telemetry/v1/configuration.rb +0 -25
- data/lib/datadog/core/telemetry/v1/dependency.rb +0 -43
- data/lib/datadog/core/telemetry/v1/host.rb +0 -59
- data/lib/datadog/core/telemetry/v1/install_signature.rb +0 -38
- data/lib/datadog/core/telemetry/v1/integration.rb +0 -64
- data/lib/datadog/core/telemetry/v1/product.rb +0 -36
- data/lib/datadog/core/telemetry/v1/telemetry_request.rb +0 -106
- data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +0 -41
- data/lib/datadog/core/telemetry/v2/request.rb +0 -29
- data/lib/datadog/profiling/diagnostics/environment_logger.rb +0 -39
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/NativeExtensionDesign.md +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_from_pthread.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_noop.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_gc_profiling_helper.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_gc_profiling_helper.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/helpers.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.h +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.c +0 -0
- /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.h +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'emitter'
|
|
4
|
+
require_relative 'event'
|
|
4
5
|
require_relative 'heartbeat'
|
|
5
6
|
require_relative '../utils/forking'
|
|
6
7
|
|
|
@@ -10,21 +11,25 @@ module Datadog
|
|
|
10
11
|
# Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
|
|
11
12
|
class Client
|
|
12
13
|
attr_reader \
|
|
13
|
-
:emitter,
|
|
14
14
|
:enabled,
|
|
15
|
-
:unsupported
|
|
16
|
-
:worker
|
|
15
|
+
:unsupported
|
|
17
16
|
|
|
18
17
|
include Core::Utils::Forking
|
|
19
18
|
|
|
20
19
|
# @param enabled [Boolean] Determines whether telemetry events should be sent to the API
|
|
21
20
|
# @param heartbeat_interval_seconds [Float] How frequently heartbeats will be reported, in seconds.
|
|
22
|
-
|
|
21
|
+
# @param [Boolean] dependency_collection Whether to send the `app-dependencies-loaded` event
|
|
22
|
+
def initialize(heartbeat_interval_seconds:, dependency_collection:, enabled: true)
|
|
23
23
|
@enabled = enabled
|
|
24
24
|
@emitter = Emitter.new
|
|
25
25
|
@stopped = false
|
|
26
26
|
@unsupported = false
|
|
27
|
+
@started = false
|
|
28
|
+
@dependency_collection = dependency_collection
|
|
29
|
+
|
|
27
30
|
@worker = Telemetry::Heartbeat.new(enabled: @enabled, heartbeat_interval_seconds: heartbeat_interval_seconds) do
|
|
31
|
+
next unless @started # `started!` should be the first event, thus ensure that `heartbeat!` is not sent first.
|
|
32
|
+
|
|
28
33
|
heartbeat!
|
|
29
34
|
end
|
|
30
35
|
end
|
|
@@ -37,21 +42,24 @@ module Datadog
|
|
|
37
42
|
def started!
|
|
38
43
|
return if !@enabled || forked?
|
|
39
44
|
|
|
40
|
-
res = @emitter.request(
|
|
45
|
+
res = @emitter.request(Event::AppStarted.new)
|
|
41
46
|
|
|
42
47
|
if res.not_found? # Telemetry is only supported by agent versions 7.34 and up
|
|
43
48
|
Datadog.logger.debug('Agent does not support telemetry; disabling future telemetry events.')
|
|
44
49
|
disable!
|
|
45
50
|
@unsupported = true # Prevent telemetry from getting re-enabled
|
|
51
|
+
return res
|
|
46
52
|
end
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
@emitter.request(Event::AppDependenciesLoaded.new) if @dependency_collection
|
|
55
|
+
|
|
56
|
+
@started = true
|
|
49
57
|
end
|
|
50
58
|
|
|
51
59
|
def emit_closing!
|
|
52
60
|
return if !@enabled || forked?
|
|
53
61
|
|
|
54
|
-
@emitter.request(
|
|
62
|
+
@emitter.request(Event::AppClosing.new)
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
def stop!
|
|
@@ -64,14 +72,14 @@ module Datadog
|
|
|
64
72
|
def integrations_change!
|
|
65
73
|
return if !@enabled || forked?
|
|
66
74
|
|
|
67
|
-
@emitter.request(
|
|
75
|
+
@emitter.request(Event::AppIntegrationsChange.new)
|
|
68
76
|
end
|
|
69
77
|
|
|
70
78
|
# Report configuration changes caused by Remote Configuration.
|
|
71
79
|
def client_configuration_change!(changes)
|
|
72
80
|
return if !@enabled || forked?
|
|
73
81
|
|
|
74
|
-
@emitter.request(
|
|
82
|
+
@emitter.request(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
|
|
75
83
|
end
|
|
76
84
|
|
|
77
85
|
private
|
|
@@ -79,7 +87,7 @@ module Datadog
|
|
|
79
87
|
def heartbeat!
|
|
80
88
|
return if !@enabled || forked?
|
|
81
89
|
|
|
82
|
-
@emitter.request(
|
|
90
|
+
@emitter.request(Event::AppHeartbeat.new)
|
|
83
91
|
end
|
|
84
92
|
end
|
|
85
93
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require_relative '
|
|
1
|
+
require_relative 'request'
|
|
2
2
|
require_relative 'http/transport'
|
|
3
3
|
require_relative '../utils/sequence'
|
|
4
4
|
require_relative '../utils/forking'
|
|
@@ -12,7 +12,6 @@ module Datadog
|
|
|
12
12
|
|
|
13
13
|
extend Core::Utils::Forking
|
|
14
14
|
|
|
15
|
-
# @param sequence [Datadog::Core::Utils::Sequence] Sequence object that stores and increments a counter
|
|
16
15
|
# @param http_transport [Datadog::Core::Telemetry::Http::Transport] Transport object that can be used to send
|
|
17
16
|
# telemetry requests via the agent
|
|
18
17
|
def initialize(http_transport: Datadog::Core::Telemetry::Http::Transport.new)
|
|
@@ -20,18 +19,15 @@ module Datadog
|
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
# Retrieves and emits a TelemetryRequest object based on the request type specified
|
|
23
|
-
|
|
24
|
-
# @param data [Object] arbitrary object to be passed to the respective `request_type` handler
|
|
25
|
-
def request(request_type, data: nil)
|
|
22
|
+
def request(event)
|
|
26
23
|
begin
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Datadog.logger.debug("Unable to send telemetry request for event `#{request_type}`: #{e}")
|
|
24
|
+
seq_id = self.class.sequence.next
|
|
25
|
+
payload = Request.build_payload(event, seq_id)
|
|
26
|
+
res = @http_transport.request(request_type: event.type, payload: payload.to_json)
|
|
27
|
+
Datadog.logger.debug { "Telemetry sent for event `#{event.type}` (status code: #{res.code})" }
|
|
28
|
+
res
|
|
29
|
+
rescue => e
|
|
30
|
+
Datadog.logger.debug("Unable to send telemetry request for event `#{event.type rescue 'unknown'}`: #{e}")
|
|
35
31
|
Telemetry::Http::InternalErrorResponse.new(e)
|
|
36
32
|
end
|
|
37
33
|
end
|
|
@@ -1,81 +1,271 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'collector'
|
|
4
|
-
require_relative 'v1/app_event'
|
|
5
|
-
require_relative 'v1/telemetry_request'
|
|
6
|
-
require_relative 'v2/app_client_configuration_change'
|
|
7
|
-
|
|
8
3
|
module Datadog
|
|
9
4
|
module Core
|
|
10
5
|
module Telemetry
|
|
11
|
-
# Class defining methods to construct a Telemetry event
|
|
12
6
|
class Event
|
|
13
|
-
|
|
7
|
+
# Base class for all Telemetry V2 events.
|
|
8
|
+
class Base
|
|
9
|
+
# The type of the event.
|
|
10
|
+
# It must be one of the stings defined in the Telemetry V2
|
|
11
|
+
# specification for event names.
|
|
12
|
+
def type; end
|
|
13
|
+
|
|
14
|
+
# The JSON payload for the event.
|
|
15
|
+
# @param seq_id [Integer] The sequence ID for the event.
|
|
16
|
+
def payload(seq_id)
|
|
17
|
+
{}
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Telemetry class for the 'app-started' event
|
|
22
|
+
class AppStarted < Base
|
|
23
|
+
def type
|
|
24
|
+
'app-started'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def payload(seq_id)
|
|
28
|
+
@seq_id = seq_id
|
|
29
|
+
{
|
|
30
|
+
products: products,
|
|
31
|
+
configuration: configuration,
|
|
32
|
+
install_signature: install_signature,
|
|
33
|
+
# DEV: Not implemented yet
|
|
34
|
+
# error: error, # Start-up errors
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def products
|
|
41
|
+
products = {
|
|
42
|
+
appsec: {
|
|
43
|
+
enabled: Datadog::AppSec.enabled?,
|
|
44
|
+
},
|
|
45
|
+
profiler: {
|
|
46
|
+
enabled: Datadog::Profiling.enabled?,
|
|
47
|
+
},
|
|
48
|
+
# DEV: Not implemented yet
|
|
49
|
+
# dynamic_instrumentation: {
|
|
50
|
+
# enabled: true,
|
|
51
|
+
# }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (unsupported_reason = Datadog::Profiling.unsupported_reason)
|
|
55
|
+
products[:profiler][:error] = {
|
|
56
|
+
code: 1, # Error code. 0 if no error.
|
|
57
|
+
message: unsupported_reason,
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
products
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
TARGET_OPTIONS = %w[
|
|
65
|
+
logger.level
|
|
66
|
+
profiling.advanced.code_provenance_enabled
|
|
67
|
+
profiling.advanced.endpoint.collection.enabled
|
|
68
|
+
profiling.enabled
|
|
69
|
+
runtime_metrics.enabled
|
|
70
|
+
tracing.analytics.enabled
|
|
71
|
+
tracing.distributed_tracing.propagation_inject_style
|
|
72
|
+
tracing.distributed_tracing.propagation_extract_style
|
|
73
|
+
tracing.enabled
|
|
74
|
+
tracing.log_injection
|
|
75
|
+
tracing.partial_flush.enabled
|
|
76
|
+
tracing.partial_flush.min_spans_threshold
|
|
77
|
+
tracing.report_hostname
|
|
78
|
+
tracing.sampling.rate_limit
|
|
79
|
+
].freeze
|
|
80
|
+
|
|
81
|
+
# rubocop:disable Metrics/AbcSize
|
|
82
|
+
def configuration
|
|
83
|
+
config = Datadog.configuration
|
|
84
|
+
|
|
85
|
+
list = [
|
|
86
|
+
conf_value('DD_AGENT_HOST', config.agent.host),
|
|
87
|
+
conf_value('DD_AGENT_TRANSPORT', agent_transport(config)),
|
|
88
|
+
conf_value('DD_TRACE_SAMPLE_RATE', to_value(config.tracing.sampling.default_rate)),
|
|
89
|
+
conf_value(
|
|
90
|
+
'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
|
|
91
|
+
config.tracing.contrib.global_default_service_name.enabled
|
|
92
|
+
),
|
|
93
|
+
]
|
|
14
94
|
|
|
15
|
-
|
|
95
|
+
peer_service_mapping_str = ''
|
|
96
|
+
unless config.tracing.contrib.peer_service_mapping.empty?
|
|
97
|
+
peer_service_mapping = config.tracing.contrib.peer_service_mapping
|
|
98
|
+
peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
|
|
99
|
+
end
|
|
100
|
+
list << conf_value('DD_TRACE_PEER_SERVICE_MAPPING', peer_service_mapping_str)
|
|
16
101
|
|
|
17
|
-
|
|
18
|
-
|
|
102
|
+
# Whitelist of configuration options to send in additional payload object
|
|
103
|
+
TARGET_OPTIONS.each do |option|
|
|
104
|
+
split_option = option.split('.')
|
|
105
|
+
list << conf_value(option, to_value(config.dig(*split_option)))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Add some more custom additional payload values here
|
|
109
|
+
list.push(
|
|
110
|
+
conf_value('tracing.auto_instrument.enabled', !defined?(Datadog::AutoInstrument::LOADED).nil?),
|
|
111
|
+
conf_value('tracing.writer_options.buffer_size', to_value(config.tracing.writer_options[:buffer_size])),
|
|
112
|
+
conf_value('tracing.writer_options.flush_interval', to_value(config.tracing.writer_options[:flush_interval])),
|
|
113
|
+
conf_value('tracing.opentelemetry.enabled', !defined?(Datadog::OpenTelemetry::LOADED).nil?),
|
|
114
|
+
)
|
|
115
|
+
list << conf_value('logger.instance', config.logger.instance.class.to_s) if config.logger.instance
|
|
116
|
+
list << conf_value('appsec.enabled', config.dig('appsec', 'enabled')) if config.respond_to?('appsec')
|
|
117
|
+
list << conf_value('ci.enabled', config.dig('ci', 'enabled')) if config.respond_to?('ci')
|
|
118
|
+
|
|
119
|
+
list.reject! { |entry| entry[:value].nil? }
|
|
120
|
+
list
|
|
121
|
+
end
|
|
122
|
+
# rubocop:enable Metrics/AbcSize
|
|
123
|
+
|
|
124
|
+
def agent_transport(config)
|
|
125
|
+
adapter = Core::Configuration::AgentSettingsResolver.call(config).adapter
|
|
126
|
+
if adapter == Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
|
|
127
|
+
'UDS'
|
|
128
|
+
else
|
|
129
|
+
'TCP'
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def conf_value(name, value, origin = 'code')
|
|
134
|
+
{
|
|
135
|
+
name: name,
|
|
136
|
+
value: value,
|
|
137
|
+
origin: origin,
|
|
138
|
+
seq_id: @seq_id,
|
|
139
|
+
}
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def to_value(value)
|
|
143
|
+
# TODO: Add float if telemetry starts accepting it
|
|
144
|
+
case value
|
|
145
|
+
when Integer, String, true, false, nil
|
|
146
|
+
value
|
|
147
|
+
else
|
|
148
|
+
value.to_s
|
|
149
|
+
end
|
|
150
|
+
end
|
|
19
151
|
|
|
20
|
-
|
|
21
|
-
|
|
152
|
+
def install_signature
|
|
153
|
+
config = Datadog.configuration
|
|
154
|
+
{
|
|
155
|
+
install_id: config.dig('telemetry', 'install_id'),
|
|
156
|
+
install_type: config.dig('telemetry', 'install_type'),
|
|
157
|
+
install_time: config.dig('telemetry', 'install_time'),
|
|
158
|
+
}
|
|
159
|
+
end
|
|
22
160
|
end
|
|
23
161
|
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
162
|
+
# Telemetry class for the 'app-dependencies-loaded' event
|
|
163
|
+
class AppDependenciesLoaded < Base
|
|
164
|
+
def type
|
|
165
|
+
'app-dependencies-loaded'
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def payload(seq_id)
|
|
169
|
+
{ dependencies: dependencies }
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
private
|
|
173
|
+
|
|
174
|
+
def dependencies
|
|
175
|
+
Gem.loaded_specs.collect do |name, gem|
|
|
176
|
+
{
|
|
177
|
+
name: name,
|
|
178
|
+
version: gem.version.to_s,
|
|
179
|
+
# hash: nil,
|
|
180
|
+
}
|
|
181
|
+
end
|
|
182
|
+
end
|
|
39
183
|
end
|
|
40
184
|
|
|
41
|
-
|
|
185
|
+
# Telemetry class for the 'app-integrations-change' event
|
|
186
|
+
class AppIntegrationsChange < Base
|
|
187
|
+
def type
|
|
188
|
+
'app-integrations-change'
|
|
189
|
+
end
|
|
42
190
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
191
|
+
def payload(seq_id)
|
|
192
|
+
{ integrations: integrations }
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
private
|
|
196
|
+
|
|
197
|
+
def integrations
|
|
198
|
+
instrumented_integrations = Datadog.configuration.tracing.instrumented_integrations
|
|
199
|
+
Datadog.registry.map do |integration|
|
|
200
|
+
is_instrumented = instrumented_integrations.include?(integration.name)
|
|
201
|
+
|
|
202
|
+
is_enabled = is_instrumented ? !!integration.klass.patcher.patch_successful : false
|
|
203
|
+
|
|
204
|
+
version = integration.klass.class.version ? integration.klass.class.version.to_s : nil
|
|
205
|
+
|
|
206
|
+
res = {
|
|
207
|
+
name: integration.name.to_s,
|
|
208
|
+
enabled: is_enabled,
|
|
209
|
+
version: version,
|
|
210
|
+
compatible: integration.klass.class.compatible?,
|
|
211
|
+
error: (patch_error(integration) if is_instrumented && !is_enabled),
|
|
212
|
+
# TODO: Track if integration is instrumented by manual configuration or by auto instrumentation
|
|
213
|
+
# auto_enabled: is_enabled && ???,
|
|
214
|
+
}
|
|
215
|
+
res.reject! { |_, v| v.nil? }
|
|
216
|
+
res
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def patch_error(integration)
|
|
221
|
+
patch_error_result = integration.klass.patcher.patch_error_result
|
|
222
|
+
return patch_error_result.compact.to_s if patch_error_result
|
|
223
|
+
|
|
224
|
+
# If no error occurred during patching, but integration is still not instrumented
|
|
225
|
+
"Available?: #{integration.klass.class.available?}" \
|
|
226
|
+
", Loaded? #{integration.klass.class.loaded?}" \
|
|
227
|
+
", Compatible? #{integration.klass.class.compatible?}" \
|
|
228
|
+
", Patchable? #{integration.klass.class.patchable?}"
|
|
55
229
|
end
|
|
56
230
|
end
|
|
57
231
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
232
|
+
# Telemetry class for the 'app-client-configuration-change' event
|
|
233
|
+
class AppClientConfigurationChange < Base
|
|
234
|
+
def type
|
|
235
|
+
'app-client-configuration-change'
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def initialize(changes, origin)
|
|
239
|
+
super()
|
|
240
|
+
@changes = changes
|
|
241
|
+
@origin = origin
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def payload(seq_id)
|
|
245
|
+
{
|
|
246
|
+
configuration: @changes.map do |name, value|
|
|
247
|
+
{
|
|
248
|
+
name: name,
|
|
249
|
+
value: value,
|
|
250
|
+
origin: @origin,
|
|
251
|
+
}
|
|
252
|
+
end
|
|
253
|
+
}
|
|
254
|
+
end
|
|
66
255
|
end
|
|
67
256
|
|
|
68
|
-
|
|
69
|
-
|
|
257
|
+
# Telemetry class for the 'app-heartbeat' event
|
|
258
|
+
class AppHeartbeat < Base
|
|
259
|
+
def type
|
|
260
|
+
'app-heartbeat'
|
|
261
|
+
end
|
|
70
262
|
end
|
|
71
263
|
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def app_client_configuration_change(data)
|
|
78
|
-
Telemetry::V2::AppClientConfigurationChange.new(data[:changes], origin: data[:origin])
|
|
264
|
+
# Telemetry class for the 'app-closing' event
|
|
265
|
+
class AppClosing < Base
|
|
266
|
+
def type
|
|
267
|
+
'app-closing'
|
|
268
|
+
end
|
|
79
269
|
end
|
|
80
270
|
end
|
|
81
271
|
end
|
|
@@ -6,6 +6,7 @@ module Datadog
|
|
|
6
6
|
module Ext
|
|
7
7
|
ENV_ENABLED = 'DD_INSTRUMENTATION_TELEMETRY_ENABLED'
|
|
8
8
|
ENV_HEARTBEAT_INTERVAL = 'DD_TELEMETRY_HEARTBEAT_INTERVAL'
|
|
9
|
+
ENV_DEPENDENCY_COLLECTION = 'DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED'
|
|
9
10
|
ENV_INSTALL_ID = 'DD_INSTRUMENTATION_INSTALL_ID'
|
|
10
11
|
ENV_INSTALL_TYPE = 'DD_INSTRUMENTATION_INSTALL_TYPE'
|
|
11
12
|
ENV_INSTALL_TIME = 'DD_INSTRUMENTATION_INSTALL_TIME'
|
|
@@ -10,9 +10,12 @@ module Datadog
|
|
|
10
10
|
HEADER_CONTENT_LENGTH = 'Content-Length'
|
|
11
11
|
HEADER_DD_TELEMETRY_API_VERSION = 'DD-Telemetry-API-Version'
|
|
12
12
|
HEADER_DD_TELEMETRY_REQUEST_TYPE = 'DD-Telemetry-Request-Type'
|
|
13
|
+
HEADER_TELEMETRY_DEBUG_ENABLED = 'DD-Telemetry-Debug-Enabled'
|
|
14
|
+
HEADER_CLIENT_LIBRARY_LANGUAGE = 'DD-Client-Library-Language'
|
|
15
|
+
HEADER_CLIENT_LIBRARY_VERSION = 'DD-Client-Library-Version'
|
|
13
16
|
|
|
14
17
|
CONTENT_TYPE_APPLICATION_JSON = 'application/json'
|
|
15
|
-
API_VERSION = '
|
|
18
|
+
API_VERSION = 'v2'
|
|
16
19
|
|
|
17
20
|
AGENT_ENDPOINT = '/telemetry/proxy/api/v2/apmtelemetry'
|
|
18
21
|
end
|
|
@@ -39,10 +39,15 @@ module Datadog
|
|
|
39
39
|
|
|
40
40
|
def headers(request_type:, api_version: Http::Ext::API_VERSION)
|
|
41
41
|
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST => '1',
|
|
43
|
+
Ext::HEADER_CONTENT_TYPE => Http::Ext::CONTENT_TYPE_APPLICATION_JSON,
|
|
44
|
+
Ext::HEADER_DD_TELEMETRY_API_VERSION => api_version,
|
|
45
|
+
Ext::HEADER_DD_TELEMETRY_REQUEST_TYPE => request_type,
|
|
46
|
+
Ext::HEADER_CLIENT_LIBRARY_LANGUAGE => Core::Environment::Ext::LANG,
|
|
47
|
+
Ext::HEADER_CLIENT_LIBRARY_VERSION => DDTrace::VERSION::STRING,
|
|
48
|
+
|
|
49
|
+
# Enable debug mode for telemetry
|
|
50
|
+
# HEADER_TELEMETRY_DEBUG_ENABLED => 'true',
|
|
46
51
|
}
|
|
47
52
|
end
|
|
48
53
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../environment/platform'
|
|
4
|
+
require_relative '../utils/hash'
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module Core
|
|
8
|
+
module Telemetry
|
|
9
|
+
# Module defining methods for collecting metadata for telemetry
|
|
10
|
+
module Request
|
|
11
|
+
class << self
|
|
12
|
+
using Core::Utils::Hash::Refinement
|
|
13
|
+
|
|
14
|
+
def build_payload(event, seq_id)
|
|
15
|
+
hash = {
|
|
16
|
+
api_version: Http::Ext::API_VERSION,
|
|
17
|
+
application: application,
|
|
18
|
+
debug: false,
|
|
19
|
+
host: host,
|
|
20
|
+
payload: event.payload(seq_id),
|
|
21
|
+
request_type: event.type,
|
|
22
|
+
runtime_id: Core::Environment::Identity.id,
|
|
23
|
+
seq_id: seq_id,
|
|
24
|
+
tracer_time: Time.now.to_i,
|
|
25
|
+
}
|
|
26
|
+
hash.compact!
|
|
27
|
+
hash
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def application
|
|
33
|
+
config = Datadog.configuration
|
|
34
|
+
{
|
|
35
|
+
env: config.env,
|
|
36
|
+
language_name: Core::Environment::Ext::LANG,
|
|
37
|
+
language_version: Core::Environment::Ext::LANG_VERSION,
|
|
38
|
+
runtime_name: Core::Environment::Ext::RUBY_ENGINE,
|
|
39
|
+
runtime_version: Core::Environment::Ext::ENGINE_VERSION,
|
|
40
|
+
service_name: config.service,
|
|
41
|
+
service_version: config.version,
|
|
42
|
+
tracer_version: Core::Environment::Identity.tracer_version
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def host
|
|
47
|
+
{
|
|
48
|
+
architecture: Core::Environment::Platform.architecture,
|
|
49
|
+
hostname: Core::Environment::Platform.hostname,
|
|
50
|
+
kernel_name: Core::Environment::Platform.kernel_name,
|
|
51
|
+
kernel_release: Core::Environment::Platform.kernel_release,
|
|
52
|
+
kernel_version: Core::Environment::Platform.kernel_version
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -25,6 +25,8 @@ module Datadog
|
|
|
25
25
|
HEADER_META_LANG = 'Datadog-Meta-Lang'
|
|
26
26
|
HEADER_META_LANG_VERSION = 'Datadog-Meta-Lang-Version'
|
|
27
27
|
HEADER_META_LANG_INTERPRETER = 'Datadog-Meta-Lang-Interpreter'
|
|
28
|
+
# Use for distinguishing between CRuby, JRuby, and TruffleRuby.
|
|
29
|
+
HEADER_META_LANG_INTERPRETER_VENDOR = 'Datadog-Meta-Lang-Interpreter-Vendor'
|
|
28
30
|
HEADER_META_TRACER_VERSION = 'Datadog-Meta-Tracer-Version'
|
|
29
31
|
|
|
30
32
|
# Header that prevents the Net::HTTP integration from tracing internal trace requests.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Core
|
|
7
|
+
module Utils
|
|
8
|
+
# Helpers class that provides methods to process URLs
|
|
9
|
+
# such as filtering sensitive information.
|
|
10
|
+
module Url
|
|
11
|
+
def self.filter_basic_auth(url)
|
|
12
|
+
return nil if url.nil?
|
|
13
|
+
|
|
14
|
+
URI(url).tap do |u|
|
|
15
|
+
u.user = nil
|
|
16
|
+
u.password = nil
|
|
17
|
+
end.to_s
|
|
18
|
+
# Git scheme: git@github.com:DataDog/dd-trace-rb.git
|
|
19
|
+
rescue URI::InvalidURIError
|
|
20
|
+
url
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -97,14 +97,20 @@ module Datadog
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
# Represents metadata we have for a ruby gem
|
|
101
|
+
class Library
|
|
102
|
+
attr_reader :kind, :name, :version, :path
|
|
103
|
+
|
|
101
104
|
def initialize(kind:, name:, version:, path:)
|
|
102
|
-
|
|
105
|
+
@kind = kind.freeze
|
|
106
|
+
@name = name.dup.freeze
|
|
107
|
+
@version = version.to_s.dup.freeze
|
|
108
|
+
@path = path.dup.freeze
|
|
103
109
|
freeze
|
|
104
110
|
end
|
|
105
111
|
|
|
106
|
-
def to_json(
|
|
107
|
-
{ kind: kind, name: name, version: version, paths: [path] }.to_json(
|
|
112
|
+
def to_json(arg = nil)
|
|
113
|
+
{ kind: @kind, name: @name, version: @version, paths: [@path] }.to_json(arg)
|
|
108
114
|
end
|
|
109
115
|
end
|
|
110
116
|
end
|