ddtrace 1.21.1 → 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 +39 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +32 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +5 -2
- data/ext/datadog_profiling_native_extension/heap_recorder.c +45 -3
- data/ext/datadog_profiling_native_extension/heap_recorder.h +7 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +5 -5
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +1 -1
- data/ext/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/core/configuration/components.rb +2 -1
- data/lib/datadog/core/configuration/option.rb +7 -5
- data/lib/datadog/core/configuration/settings.rb +38 -17
- data/lib/datadog/core/configuration.rb +20 -4
- data/lib/datadog/core/environment/platform.rb +7 -1
- data/lib/datadog/core/remote/client/capabilities.rb +1 -1
- data/lib/datadog/core/remote/transport/http/config.rb +1 -1
- 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/profiling/collectors/code_provenance.rb +10 -4
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +25 -0
- data/lib/datadog/profiling/component.rb +23 -15
- data/lib/datadog/profiling/load_native_extension.rb +14 -1
- data/lib/datadog/profiling.rb +11 -0
- 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/ddtrace/version.rb +2 -2
- metadata +6 -17
- 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
@@ -266,7 +266,10 @@ module Datadog
|
|
266
266
|
|
267
267
|
# Can be used to disable the gathering of names and versions of gems in use by the service, used to power
|
268
268
|
# grouping and categorization of stack traces.
|
269
|
-
option :code_provenance_enabled
|
269
|
+
option :code_provenance_enabled do |o|
|
270
|
+
o.type :bool
|
271
|
+
o.default true
|
272
|
+
end
|
270
273
|
|
271
274
|
# @deprecated No longer does anything, and will be removed on dd-trace-rb 2.0.
|
272
275
|
#
|
@@ -313,27 +316,35 @@ module Datadog
|
|
313
316
|
end
|
314
317
|
end
|
315
318
|
|
316
|
-
#
|
319
|
+
# @deprecated No longer does anything, and will be removed on dd-trace-rb 2.0.
|
317
320
|
#
|
318
|
-
#
|
319
|
-
|
321
|
+
# GC profiling is now on by default and controlled by {:gc_enabled}.
|
322
|
+
option :force_enable_gc_profiling do |o|
|
323
|
+
o.after_set do |_, _, precedence|
|
324
|
+
unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
|
325
|
+
Datadog.logger.warn(
|
326
|
+
'The profiling.advanced.force_enable_gc_profiling setting has been deprecated for removal and no ' \
|
327
|
+
'longer does anything (the feature is now on by default). ' \
|
328
|
+
'Please remove this setting from your Datadog.configure block.'
|
329
|
+
)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# Can be used to enable/disable garbage collection profiling.
|
320
335
|
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
# Ractors due to two Ruby VM bugs:
|
325
|
-
# https://bugs.ruby-lang.org/issues/19112 AND https://bugs.ruby-lang.org/issues/18464.
|
326
|
-
# If you use Ruby 3.x and your application does not use Ractors (or if your Ruby has been patched), the
|
327
|
-
# feature is fully safe to enable and this toggle can be used to do so.
|
336
|
+
# @warn To avoid https://bugs.ruby-lang.org/issues/18464 even when enabled, GC profiling is only started
|
337
|
+
# for Ruby versions 2.x, 3.1.4+, 3.2.3+ and 3.3.0+
|
338
|
+
# (more details in {Datadog::Profiling::Component.enable_gc_profiling?})
|
328
339
|
#
|
329
|
-
#
|
330
|
-
#
|
340
|
+
# @warn Due to a VM bug in the Ractor implementation (https://bugs.ruby-lang.org/issues/19112) this feature
|
341
|
+
# stops working when Ractors get garbage collected.
|
331
342
|
#
|
332
|
-
# @default `
|
333
|
-
option :
|
334
|
-
o.env 'DD_PROFILING_FORCE_ENABLE_GC'
|
343
|
+
# @default `DD_PROFILING_GC_ENABLED` environment variable, otherwise `true`
|
344
|
+
option :gc_enabled do |o|
|
335
345
|
o.type :bool
|
336
|
-
o.
|
346
|
+
o.env 'DD_PROFILING_GC_ENABLED'
|
347
|
+
o.default true
|
337
348
|
end
|
338
349
|
|
339
350
|
# Can be used to enable/disable the Datadog::Profiling.allocation_count feature.
|
@@ -687,6 +698,16 @@ module Datadog
|
|
687
698
|
# Client-side telemetry configuration
|
688
699
|
# @public_api
|
689
700
|
settings :telemetry do
|
701
|
+
# Whether the bundled Ruby gems as reported through telemetry.
|
702
|
+
#
|
703
|
+
# @default `DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED` environment variable, otherwise `true`.
|
704
|
+
# @return [Boolean]
|
705
|
+
option :dependency_collection do |o|
|
706
|
+
o.type :bool
|
707
|
+
o.env Core::Telemetry::Ext::ENV_DEPENDENCY_COLLECTION
|
708
|
+
o.default true
|
709
|
+
end
|
710
|
+
|
690
711
|
# Enable telemetry collection. This allows telemetry events to be emitted to the telemetry API.
|
691
712
|
#
|
692
713
|
# @default `DD_INSTRUMENTATION_TELEMETRY_ENABLED` environment variable, otherwise `true`.
|
@@ -81,18 +81,23 @@ module Datadog
|
|
81
81
|
configuration = self.configuration
|
82
82
|
yield(configuration)
|
83
83
|
|
84
|
-
|
84
|
+
built_components = false
|
85
|
+
|
86
|
+
components = safely_synchronize do |write_components|
|
85
87
|
write_components.call(
|
86
88
|
if components?
|
87
89
|
replace_components!(configuration, @components)
|
88
90
|
else
|
89
91
|
components = build_components(configuration)
|
90
|
-
|
92
|
+
built_components = true
|
91
93
|
components
|
92
94
|
end
|
93
95
|
)
|
94
96
|
end
|
95
97
|
|
98
|
+
# Should only be called the first time components are built
|
99
|
+
components.telemetry.started! if built_components
|
100
|
+
|
96
101
|
configuration
|
97
102
|
end
|
98
103
|
|
@@ -192,9 +197,20 @@ module Datadog
|
|
192
197
|
current_components = COMPONENTS_READ_LOCK.synchronize { defined?(@components) && @components }
|
193
198
|
return current_components if current_components || !allow_initialization
|
194
199
|
|
195
|
-
|
196
|
-
|
200
|
+
built_components = false
|
201
|
+
|
202
|
+
components = safely_synchronize do |write_components|
|
203
|
+
if defined?(@components) && @components
|
204
|
+
@components
|
205
|
+
else
|
206
|
+
built_components = true
|
207
|
+
write_components.call(build_components(configuration))
|
208
|
+
end
|
197
209
|
end
|
210
|
+
|
211
|
+
# Should only be called the first time components are built
|
212
|
+
components.telemetry.started! if built_components && components && components.telemetry
|
213
|
+
components
|
198
214
|
end
|
199
215
|
|
200
216
|
private
|
@@ -9,12 +9,18 @@ module Datadog
|
|
9
9
|
module Platform
|
10
10
|
module_function
|
11
11
|
|
12
|
+
# @return [String] ISA of host; `uname -m`
|
13
|
+
def architecture
|
14
|
+
Identity.lang_version >= '2.2' ? Etc.uname[:machine] : Gem::Platform.local.cpu
|
15
|
+
end
|
16
|
+
|
12
17
|
# @return [String] name of host; `uname -n`
|
13
18
|
def hostname
|
14
19
|
Identity.lang_version >= '2.2' ? Etc.uname[:nodename] : nil
|
15
20
|
end
|
16
21
|
|
17
|
-
#
|
22
|
+
# System name, normally `Linux` or `Darwin` (but 'Mac OS X' on JRuby);
|
23
|
+
# @return [String] name of kernel; `uname -s`.
|
18
24
|
def kernel_name
|
19
25
|
Identity.lang_version >= '2.2' ? Etc.uname[:sysname] : Gem::Platform.local.os.capitalize
|
20
26
|
end
|
@@ -53,7 +53,7 @@ module Datadog
|
|
53
53
|
cap_to_hexs = capabilities.reduce(:|).to_s(16).tap { |s| s.size.odd? && s.prepend('0') }.scan(/\h\h/)
|
54
54
|
binary = cap_to_hexs.each_with_object([]) { |hex, acc| acc << hex }.map { |e| e.to_i(16) }.pack('C*')
|
55
55
|
|
56
|
-
Base64.
|
56
|
+
Base64.strict_encode64(binary)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -51,7 +51,7 @@ module Datadog
|
|
51
51
|
|
52
52
|
# TODO: these fallbacks should be improved
|
53
53
|
roots = payload[:roots] || []
|
54
|
-
targets = payload[:targets] || Base64.
|
54
|
+
targets = payload[:targets] || Base64.strict_encode64('{}')
|
55
55
|
target_files = payload[:target_files] || []
|
56
56
|
client_configs = payload[:client_configs] || []
|
57
57
|
|
@@ -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
|