Skip to content

Commit 651c3ba

Browse files
authored
Telemetry: inject dependencies into telemetry app started event (#5067)
1 parent 92d6689 commit 651c3ba

File tree

17 files changed

+128
-84
lines changed

17 files changed

+128
-84
lines changed

lib/datadog/core/configuration/components.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def build_data_streams(settings, agent_settings, logger)
9696
attr_reader \
9797
:health_metrics,
9898
:settings,
99+
:agent_settings,
99100
:logger,
100101
:remote,
101102
:profiler,
@@ -120,7 +121,7 @@ def initialize(settings)
120121
# This agent_settings is intended for use within Core. If you require
121122
# agent_settings within a product outside of core you should extend
122123
# the Core resolver from within your product/component's namespace.
123-
agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
124+
@agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
124125

125126
# Exposes agent capability information for detection by any components
126127
@agent_info = Core::Environment::AgentInfo.new(agent_settings, logger: @logger)
@@ -162,7 +163,7 @@ def reconfigure_sampler(settings = Datadog.configuration)
162163

163164
# Starts up components
164165
def startup!(settings, old_state: nil)
165-
telemetry.start(old_state&.telemetry_enabled?)
166+
telemetry.start(old_state&.telemetry_enabled?, components: self)
166167

167168
if settings.profiling.enabled
168169
if profiler

lib/datadog/core/telemetry/component.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,17 @@ def disable!
109109
@worker&.enabled = false
110110
end
111111

112-
def start(initial_event_is_change = false)
112+
def start(initial_event_is_change = false, components:)
113113
return if !@enabled
114114

115115
initial_event = if initial_event_is_change
116-
Event::SynthAppClientConfigurationChange.new(agent_settings: @agent_settings)
116+
Event::SynthAppClientConfigurationChange.new(
117+
components: components,
118+
)
117119
else
118-
Event::AppStarted.new(agent_settings: @agent_settings)
120+
Event::AppStarted.new(
121+
components: components,
122+
)
119123
end
120124

121125
@worker.start(initial_event)

lib/datadog/core/telemetry/event/app_started.rb

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ module Telemetry
88
module Event
99
# Telemetry class for the 'app-started' event
1010
class AppStarted < Base
11-
def initialize(agent_settings:)
12-
@agent_settings = agent_settings
11+
def initialize(components:)
12+
# To not hold a reference to the component tree, generate
13+
# the event payload here in the constructor.
14+
@configuration = configuration(components.settings, components.agent_settings)
15+
@install_signature = install_signature(components.settings)
16+
@products = products(components)
1317
end
1418

1519
def type
@@ -18,27 +22,28 @@ def type
1822

1923
def payload
2024
{
21-
products: products,
22-
configuration: configuration,
23-
install_signature: install_signature,
25+
products: @products,
26+
configuration: @configuration,
27+
install_signature: @install_signature,
2428
# DEV: Not implemented yet
2529
# error: error, # Start-up errors
2630
}
2731
end
2832

2933
private
3034

31-
def products
35+
def products(components)
3236
# @type var products: Hash[Symbol, Hash[Symbol, Hash[Symbol, String | Integer] | bool | nil]]
3337
products = {
3438
appsec: {
35-
enabled: Datadog::AppSec.enabled?,
39+
# TODO take appsec status out of component tree?
40+
enabled: components.settings.appsec.enabled,
3641
},
3742
profiler: {
38-
enabled: Datadog::Profiling.enabled?,
43+
enabled: !!components.profiler&.enabled?,
3944
},
4045
dynamic_instrumentation: {
41-
enabled: defined?(Datadog::DI) && Datadog::DI.respond_to?(:enabled?) && Datadog::DI.enabled?,
46+
enabled: !!components.dynamic_instrumentation,
4247
}
4348
}
4449

@@ -73,12 +78,11 @@ def products
7378

7479
# standard:disable Metrics/AbcSize
7580
# standard:disable Metrics/MethodLength
76-
def configuration
77-
config = Datadog.configuration
81+
def configuration(settings, agent_settings)
7882
seq_id = Event.configuration_sequence.next
7983

8084
# tracing.writer_options.buffer_size and tracing.writer_options.flush_interval have the same origin.
81-
writer_option_origin = get_telemetry_origin(config, 'tracing.writer_options')
85+
writer_option_origin = get_telemetry_origin(settings, 'tracing.writer_options')
8286

8387
list = [
8488
# Only set using env var as of June 2025
@@ -100,69 +104,69 @@ def configuration
100104
),
101105

102106
# Mix of env var, programmatic and default config, so we use unknown
103-
conf_value('DD_AGENT_TRANSPORT', agent_transport, seq_id, 'unknown'), # rubocop:disable CustomCops/EnvStringValidationCop
107+
conf_value('DD_AGENT_TRANSPORT', agent_transport(agent_settings), seq_id, 'unknown'), # rubocop:disable CustomCops/EnvStringValidationCop
104108

105109
# writer_options is defined as an option that has a Hash value.
106110
conf_value(
107111
'tracing.writer_options.buffer_size',
108-
to_value(config.tracing.writer_options[:buffer_size]),
112+
to_value(settings.tracing.writer_options[:buffer_size]),
109113
seq_id,
110114
writer_option_origin
111115
),
112116
conf_value(
113117
'tracing.writer_options.flush_interval',
114-
to_value(config.tracing.writer_options[:flush_interval]),
118+
to_value(settings.tracing.writer_options[:flush_interval]),
115119
seq_id,
116120
writer_option_origin
117121
),
118122

119-
conf_value('DD_AGENT_HOST', config.agent.host, seq_id, get_telemetry_origin(config, 'agent.host')),
123+
conf_value('DD_AGENT_HOST', settings.agent.host, seq_id, get_telemetry_origin(settings, 'agent.host')),
120124
conf_value(
121125
'DD_TRACE_SAMPLE_RATE',
122-
to_value(config.tracing.sampling.default_rate),
126+
to_value(settings.tracing.sampling.default_rate),
123127
seq_id,
124-
get_telemetry_origin(config, 'tracing.sampling.default_rate')
128+
get_telemetry_origin(settings, 'tracing.sampling.default_rate')
125129
),
126130
conf_value(
127131
'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
128-
config.tracing.contrib.global_default_service_name.enabled,
132+
settings.tracing.contrib.global_default_service_name.enabled,
129133
seq_id,
130-
get_telemetry_origin(config, 'tracing.contrib.global_default_service_name.enabled')
134+
get_telemetry_origin(settings, 'tracing.contrib.global_default_service_name.enabled')
131135
),
132136
conf_value(
133137
'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED',
134-
config.tracing.contrib.peer_service_defaults,
138+
settings.tracing.contrib.peer_service_defaults,
135139
seq_id,
136-
get_telemetry_origin(config, 'tracing.contrib.peer_service_defaults')
140+
get_telemetry_origin(settings, 'tracing.contrib.peer_service_defaults')
137141
),
138142
conf_value(
139143
'DD_TRACE_DEBUG',
140-
config.diagnostics.debug,
144+
settings.diagnostics.debug,
141145
seq_id,
142-
get_telemetry_origin(config, 'diagnostics.debug')
146+
get_telemetry_origin(settings, 'diagnostics.debug')
143147
)
144148
]
145149

146150
peer_service_mapping_str = ''
147-
unless config.tracing.contrib.peer_service_mapping.empty?
148-
peer_service_mapping = config.tracing.contrib.peer_service_mapping
151+
unless settings.tracing.contrib.peer_service_mapping.empty?
152+
peer_service_mapping = settings.tracing.contrib.peer_service_mapping
149153
peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
150154
end
151155
list << conf_value(
152156
'DD_TRACE_PEER_SERVICE_MAPPING',
153157
peer_service_mapping_str,
154158
seq_id,
155-
get_telemetry_origin(config, 'tracing.contrib.peer_service_mapping')
159+
get_telemetry_origin(settings, 'tracing.contrib.peer_service_mapping')
156160
)
157161

158162
# Whitelist of configuration options to send in additional payload object
159163
TARGET_OPTIONS.each do |option_path|
160164
split_option = option_path.split('.')
161165
list << conf_value(
162166
option_path,
163-
to_value(config.dig(*split_option)),
167+
to_value(settings.dig(*split_option)),
164168
seq_id,
165-
get_telemetry_origin(config, option_path)
169+
get_telemetry_origin(settings, option_path)
166170
)
167171
end
168172

@@ -181,34 +185,34 @@ def configuration
181185
)
182186

183187
# Add some more custom additional payload values here
184-
if config.logger.instance
188+
if settings.logger.instance
185189
list << conf_value(
186190
'logger.instance',
187-
config.logger.instance.class.to_s,
191+
settings.logger.instance.class.to_s,
188192
seq_id,
189-
get_telemetry_origin(config, 'logger.instance')
193+
get_telemetry_origin(settings, 'logger.instance')
190194
)
191195
end
192-
if config.respond_to?('appsec')
196+
if settings.respond_to?('appsec')
193197
list << conf_value(
194198
'appsec.enabled',
195-
config.dig('appsec', 'enabled'),
199+
settings.dig('appsec', 'enabled'),
196200
seq_id,
197-
get_telemetry_origin(config, 'appsec.enabled')
201+
get_telemetry_origin(settings, 'appsec.enabled')
198202
)
199203
list << conf_value(
200204
'appsec.sca_enabled',
201-
config.dig('appsec', 'sca_enabled'),
205+
settings.dig('appsec', 'sca_enabled'),
202206
seq_id,
203-
get_telemetry_origin(config, 'appsec.sca_enabled')
207+
get_telemetry_origin(settings, 'appsec.sca_enabled')
204208
)
205209
end
206-
if config.respond_to?('ci')
210+
if settings.respond_to?('ci')
207211
list << conf_value(
208212
'ci.enabled',
209-
config.dig('ci', 'enabled'),
213+
settings.dig('ci', 'enabled'),
210214
seq_id,
211-
get_telemetry_origin(config, 'ci.enabled')
215+
get_telemetry_origin(settings, 'ci.enabled')
212216
)
213217
end
214218

@@ -218,8 +222,8 @@ def configuration
218222
# standard:enable Metrics/AbcSize
219223
# standard:enable Metrics/MethodLength
220224

221-
def agent_transport
222-
adapter = @agent_settings.adapter
225+
def agent_transport(agent_settings)
226+
adapter = agent_settings.adapter
223227
if adapter == Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
224228
'UDS'
225229
else
@@ -260,23 +264,22 @@ def to_value(value)
260264
end
261265
end
262266

263-
def install_signature
264-
config = Datadog.configuration
267+
def install_signature(settings)
265268
{
266-
install_id: config.dig('telemetry', 'install_id'),
267-
install_type: config.dig('telemetry', 'install_type'),
268-
install_time: config.dig('telemetry', 'install_time'),
269+
install_id: settings.dig('telemetry', 'install_id'),
270+
install_type: settings.dig('telemetry', 'install_type'),
271+
install_time: settings.dig('telemetry', 'install_time'),
269272
}
270273
end
271274

272-
def get_telemetry_origin(config, config_path)
275+
def get_telemetry_origin(settings, config_path)
273276
split_option = config_path.split('.')
274277
option_name = split_option.pop
275278
return 'unknown' if option_name.nil?
276279

277280
# @type var parent_setting: Core::Configuration::Options
278281
# @type var option: Core::Configuration::Option
279-
parent_setting = config.dig(*split_option)
282+
parent_setting = settings.dig(*split_option)
280283
option = parent_setting.send(:resolve_option, option_name.to_sym)
281284
option.precedence_set&.origin || 'unknown'
282285
end

lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def type
3333

3434
def payload
3535
{
36-
configuration: configuration,
36+
configuration: @configuration,
3737
}
3838
end
3939
end

lib/datadog/profiling.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ def self.allocation_count
6262

6363
def self.enabled?
6464
profiler = Datadog.send(:components).profiler
65-
# Use .send(...) to avoid exposing the attr_reader as an API to the outside
66-
!!profiler&.send(:scheduler)&.running?
65+
!!profiler&.enabled?
6766
end
6867

6968
def self.wait_until_running(timeout_seconds: 5)

lib/datadog/profiling/profiler.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def initialize(worker:, scheduler:)
1717
@scheduler = scheduler
1818
end
1919

20+
def enabled?
21+
scheduler.running?
22+
end
23+
2024
def start
2125
after_fork! do
2226
worker.reset_after_fork

sig/datadog/core/configuration/components.rbs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,18 @@ module Datadog
2424

2525
public
2626

27+
attr_reader settings: untyped
28+
29+
attr_reader agent_settings: untyped
30+
2731
attr_reader health_metrics: untyped
2832

2933
attr_reader logger: untyped
3034

3135
attr_reader profiler: untyped
3236

37+
attr_reader dynamic_instrumentation: untyped
38+
3339
attr_reader runtime_metrics: untyped
3440

3541
attr_reader tracer: untyped

sig/datadog/core/telemetry/component.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module Datadog
2626

2727
def disable!: () -> void
2828

29-
def start: (?bool initial_event_is_change) -> void
29+
def start: (?bool initial_event_is_change, components: Datadog::Core::Configuration::Components) -> void
3030

3131
def shutdown!: () -> void
3232

sig/datadog/core/telemetry/event/app_started.rbs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,28 @@ module Datadog
33
module Telemetry
44
module Event
55
class AppStarted < Base
6-
@agent_settings: Datadog::Core::Configuration::AgentSettings
7-
8-
def initialize: (agent_settings: Datadog::Core::Configuration::AgentSettings) -> void
6+
def initialize: (components: Datadog::Core::Configuration::Components) -> void
97

108
def type: () -> "app-started"
119

1210
def payload: () -> { products: untyped, configuration: untyped, install_signature: untyped }
1311

1412
private
1513

16-
def products: -> Hash[Symbol, Hash[Symbol, Hash[Symbol, String | Integer] | bool | nil]]
14+
def products: (Datadog::Core::Configuration::Components components) -> Hash[Symbol, Hash[Symbol, Hash[Symbol, String | Integer] | bool | nil]]
1715

1816
TARGET_OPTIONS: Array[String]
19-
def configuration: -> Array[Hash[Symbol, untyped]]
17+
def configuration: (untyped settings, Core::Configuration::AgentSettings agent_settings) -> Array[Hash[Symbol, untyped]]
2018

21-
def agent_transport: () -> String
19+
def agent_transport: (Core::Configuration::AgentSettings agent_settings) -> String
2220

2321
def conf_value: (String name, untyped value, Integer seq_id, String origin) -> Hash[Symbol, untyped]
2422

2523
def to_value: (Object value) -> Object
2624

27-
def install_signature: -> Hash[Symbol, Object]
25+
def install_signature: (untyped settings) -> Hash[Symbol, Object]
2826

29-
def get_telemetry_origin: (untyped config, String config_path) -> String
27+
def get_telemetry_origin: (untyped settings, String config_path) -> String
3028
end
3129
end
3230
end

sig/datadog/profiling/profiler.rbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ module Datadog
1515
scheduler: Datadog::Profiling::Scheduler
1616
) -> void
1717

18+
def enabled?: () -> bool
19+
1820
def start: () -> void
1921

2022
def shutdown!: () -> void

0 commit comments

Comments
 (0)