cw-datadog 2.23.0.2 → 2.23.0.3
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/ext/datadog_profiling_native_extension/extconf.rb +4 -2
- data/ext/libdatadog_api/library_config.c +12 -11
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/route_extractor.rb +20 -5
- data/lib/datadog/appsec/api_security/sampler.rb +3 -1
- data/lib/datadog/appsec/assets/blocked.html +8 -0
- data/lib/datadog/appsec/assets/blocked.json +1 -1
- data/lib/datadog/appsec/assets/blocked.text +3 -1
- data/lib/datadog/appsec/assets.rb +1 -1
- data/lib/datadog/appsec/remote.rb +4 -0
- data/lib/datadog/appsec/response.rb +18 -4
- data/lib/datadog/core/cloudwise/client.rb +364 -25
- data/lib/datadog/core/cloudwise/component.rb +197 -52
- data/lib/datadog/core/cloudwise/docc_heartbeat_worker.rb +105 -0
- data/lib/datadog/core/cloudwise/docc_operation_worker.rb +191 -0
- data/lib/datadog/core/cloudwise/docc_registration_worker.rb +89 -0
- data/lib/datadog/core/cloudwise/license_worker.rb +3 -1
- data/lib/datadog/core/cloudwise/probe_state.rb +134 -12
- data/lib/datadog/core/configuration/components.rb +10 -9
- data/lib/datadog/core/configuration/settings.rb +28 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +5 -2
- data/lib/datadog/core/remote/client/capabilities.rb +7 -0
- data/lib/datadog/core/remote/component.rb +2 -2
- data/lib/datadog/core/remote/transport/config.rb +2 -10
- data/lib/datadog/core/remote/transport/http/config.rb +9 -9
- data/lib/datadog/core/remote/transport/http/negotiation.rb +17 -8
- data/lib/datadog/core/remote/transport/http.rb +2 -0
- data/lib/datadog/core/remote/transport/negotiation.rb +2 -18
- data/lib/datadog/core/remote/worker.rb +23 -35
- data/lib/datadog/core/telemetry/component.rb +26 -13
- data/lib/datadog/core/telemetry/event/app_started.rb +67 -49
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -6
- data/lib/datadog/core/telemetry/transport/telemetry.rb +1 -2
- data/lib/datadog/core/telemetry/worker.rb +51 -6
- data/lib/datadog/core/transport/http/adapters/net.rb +2 -0
- data/lib/datadog/core/transport/http/client.rb +69 -0
- data/lib/datadog/core/utils/only_once_successful.rb +6 -2
- data/lib/datadog/data_streams/transport/http/client.rb +4 -32
- data/lib/datadog/data_streams/transport/stats.rb +1 -1
- data/lib/datadog/di/probe_notification_builder.rb +35 -13
- data/lib/datadog/di/transport/diagnostics.rb +2 -2
- data/lib/datadog/di/transport/http/diagnostics.rb +2 -4
- data/lib/datadog/di/transport/http/input.rb +2 -4
- data/lib/datadog/di/transport/input.rb +2 -2
- data/lib/datadog/open_feature/component.rb +60 -0
- data/lib/datadog/open_feature/configuration.rb +27 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +59 -0
- data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
- data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
- data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
- data/lib/datadog/open_feature/exposures/event.rb +60 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
- data/lib/datadog/open_feature/exposures/worker.rb +116 -0
- data/lib/datadog/open_feature/ext.rb +13 -0
- data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
- data/lib/datadog/open_feature/provider.rb +134 -0
- data/lib/datadog/open_feature/remote.rb +74 -0
- data/lib/datadog/open_feature/resolution_details.rb +35 -0
- data/lib/datadog/open_feature/transport.rb +72 -0
- data/lib/datadog/open_feature.rb +19 -0
- data/lib/datadog/profiling/component.rb +6 -0
- data/lib/datadog/profiling/profiler.rb +4 -0
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/tracing/contrib/cloudwise/propagation.rb +164 -7
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +22 -17
- data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +14 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +6 -2
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop.rb +37 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/transport/http/api.rb +40 -1
- data/lib/datadog/tracing/transport/http/client.rb +12 -26
- data/lib/datadog/tracing/transport/http/traces.rb +4 -2
- data/lib/datadog/tracing/transport/trace_formatter.rb +16 -0
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +1 -0
- metadata +38 -15
- data/lib/datadog/core/cloudwise/IMPLEMENTATION_V2.md +0 -517
- data/lib/datadog/core/cloudwise/QUICKSTART.md +0 -398
- data/lib/datadog/core/cloudwise/README.md +0 -722
- data/lib/datadog/core/remote/transport/http/client.rb +0 -49
- data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
- data/lib/datadog/di/transport/http/client.rb +0 -47
|
@@ -14,14 +14,23 @@ require_relative '../utils/forking'
|
|
|
14
14
|
module Datadog
|
|
15
15
|
module Core
|
|
16
16
|
module Telemetry
|
|
17
|
-
# Telemetry
|
|
18
|
-
#
|
|
17
|
+
# Telemetry entry point, coordinates sending telemetry events at
|
|
18
|
+
# various points in application lifecycle.
|
|
19
19
|
#
|
|
20
20
|
# @api private
|
|
21
21
|
class Component
|
|
22
22
|
ENDPOINT_COLLECTION_MESSAGE_LIMIT = 300
|
|
23
23
|
|
|
24
|
-
attr_reader :enabled
|
|
24
|
+
attr_reader :enabled
|
|
25
|
+
attr_reader :logger
|
|
26
|
+
attr_reader :transport
|
|
27
|
+
attr_reader :worker
|
|
28
|
+
attr_reader :settings
|
|
29
|
+
attr_reader :agent_settings
|
|
30
|
+
|
|
31
|
+
# Alias for consistency with other components.
|
|
32
|
+
# TODO Remove +enabled+ method
|
|
33
|
+
alias_method :enabled?, :enabled
|
|
25
34
|
|
|
26
35
|
include Core::Utils::Forking
|
|
27
36
|
include Telemetry::Logging
|
|
@@ -109,13 +118,17 @@ module Datadog
|
|
|
109
118
|
@worker&.enabled = false
|
|
110
119
|
end
|
|
111
120
|
|
|
112
|
-
def start(initial_event_is_change = false)
|
|
113
|
-
return
|
|
121
|
+
def start(initial_event_is_change = false, components:)
|
|
122
|
+
return unless enabled?
|
|
114
123
|
|
|
115
124
|
initial_event = if initial_event_is_change
|
|
116
|
-
Event::SynthAppClientConfigurationChange.new(
|
|
125
|
+
Event::SynthAppClientConfigurationChange.new(
|
|
126
|
+
components: components,
|
|
127
|
+
)
|
|
117
128
|
else
|
|
118
|
-
Event::AppStarted.new(
|
|
129
|
+
Event::AppStarted.new(
|
|
130
|
+
components: components,
|
|
131
|
+
)
|
|
119
132
|
end
|
|
120
133
|
|
|
121
134
|
@worker.start(initial_event)
|
|
@@ -132,19 +145,19 @@ module Datadog
|
|
|
132
145
|
end
|
|
133
146
|
|
|
134
147
|
def emit_closing!
|
|
135
|
-
return
|
|
148
|
+
return unless enabled?
|
|
136
149
|
|
|
137
150
|
@worker.enqueue(Event::AppClosing.new)
|
|
138
151
|
end
|
|
139
152
|
|
|
140
153
|
def integrations_change!
|
|
141
|
-
return
|
|
154
|
+
return unless enabled?
|
|
142
155
|
|
|
143
156
|
@worker.enqueue(Event::AppIntegrationsChange.new)
|
|
144
157
|
end
|
|
145
158
|
|
|
146
159
|
def log!(event)
|
|
147
|
-
return
|
|
160
|
+
return unless enabled? && @log_collection_enabled
|
|
148
161
|
|
|
149
162
|
@worker.enqueue(event)
|
|
150
163
|
end
|
|
@@ -155,21 +168,21 @@ module Datadog
|
|
|
155
168
|
#
|
|
156
169
|
# @api private
|
|
157
170
|
def flush
|
|
158
|
-
return
|
|
171
|
+
return unless enabled?
|
|
159
172
|
|
|
160
173
|
@worker.flush
|
|
161
174
|
end
|
|
162
175
|
|
|
163
176
|
# Report configuration changes caused by Remote Configuration.
|
|
164
177
|
def client_configuration_change!(changes)
|
|
165
|
-
return
|
|
178
|
+
return unless enabled?
|
|
166
179
|
|
|
167
180
|
@worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
|
|
168
181
|
end
|
|
169
182
|
|
|
170
183
|
# Report application endpoints
|
|
171
184
|
def app_endpoints_loaded(endpoints, page_size: ENDPOINT_COLLECTION_MESSAGE_LIMIT)
|
|
172
|
-
return
|
|
185
|
+
return unless enabled?
|
|
173
186
|
|
|
174
187
|
endpoints.each_slice(page_size).with_index do |endpoints_slice, i|
|
|
175
188
|
@worker.enqueue(Event::AppEndpointsLoaded.new(endpoints_slice, is_first: i.zero?))
|
|
@@ -8,8 +8,18 @@ module Datadog
|
|
|
8
8
|
module Event
|
|
9
9
|
# Telemetry class for the 'app-started' event
|
|
10
10
|
class AppStarted < Base
|
|
11
|
-
def initialize(
|
|
12
|
-
|
|
11
|
+
def initialize(components:)
|
|
12
|
+
# To not hold a reference to the component tree, generate
|
|
13
|
+
# the event payload here in the constructor.
|
|
14
|
+
#
|
|
15
|
+
# Important: do not store data that contains (or is derived from)
|
|
16
|
+
# the runtime_id or sequence numbers.
|
|
17
|
+
# This event is reused when a process forks, but in the
|
|
18
|
+
# child process the runtime_id would be different and sequence
|
|
19
|
+
# number is reset.
|
|
20
|
+
@configuration = configuration(components.settings, components.agent_settings)
|
|
21
|
+
@install_signature = install_signature(components.settings)
|
|
22
|
+
@products = products(components)
|
|
13
23
|
end
|
|
14
24
|
|
|
15
25
|
def type
|
|
@@ -18,27 +28,37 @@ module Datadog
|
|
|
18
28
|
|
|
19
29
|
def payload
|
|
20
30
|
{
|
|
21
|
-
products: products,
|
|
22
|
-
configuration: configuration,
|
|
23
|
-
install_signature: install_signature,
|
|
31
|
+
products: @products,
|
|
32
|
+
configuration: @configuration,
|
|
33
|
+
install_signature: @install_signature,
|
|
24
34
|
# DEV: Not implemented yet
|
|
25
35
|
# error: error, # Start-up errors
|
|
26
36
|
}
|
|
27
37
|
end
|
|
28
38
|
|
|
39
|
+
# Whether the event is actually the app-started event.
|
|
40
|
+
# For the app-started event we follow up by sending
|
|
41
|
+
# app-dependencies-loaded, if the event is
|
|
42
|
+
# app-client-configuration-change we don't send
|
|
43
|
+
# app-dependencies-loaded.
|
|
44
|
+
def app_started?
|
|
45
|
+
true
|
|
46
|
+
end
|
|
47
|
+
|
|
29
48
|
private
|
|
30
49
|
|
|
31
|
-
def products
|
|
50
|
+
def products(components)
|
|
32
51
|
# @type var products: Hash[Symbol, Hash[Symbol, Hash[Symbol, String | Integer] | bool | nil]]
|
|
33
52
|
products = {
|
|
34
53
|
appsec: {
|
|
35
|
-
|
|
54
|
+
# TODO take appsec status out of component tree?
|
|
55
|
+
enabled: components.settings.appsec.enabled,
|
|
36
56
|
},
|
|
37
57
|
profiler: {
|
|
38
|
-
enabled:
|
|
58
|
+
enabled: !!components.profiler&.enabled?,
|
|
39
59
|
},
|
|
40
60
|
dynamic_instrumentation: {
|
|
41
|
-
enabled:
|
|
61
|
+
enabled: !!components.dynamic_instrumentation,
|
|
42
62
|
}
|
|
43
63
|
}
|
|
44
64
|
|
|
@@ -73,12 +93,11 @@ module Datadog
|
|
|
73
93
|
|
|
74
94
|
# standard:disable Metrics/AbcSize
|
|
75
95
|
# standard:disable Metrics/MethodLength
|
|
76
|
-
def configuration
|
|
77
|
-
config = Datadog.configuration
|
|
96
|
+
def configuration(settings, agent_settings)
|
|
78
97
|
seq_id = Event.configuration_sequence.next
|
|
79
98
|
|
|
80
99
|
# tracing.writer_options.buffer_size and tracing.writer_options.flush_interval have the same origin.
|
|
81
|
-
writer_option_origin = get_telemetry_origin(
|
|
100
|
+
writer_option_origin = get_telemetry_origin(settings, 'tracing.writer_options')
|
|
82
101
|
|
|
83
102
|
list = [
|
|
84
103
|
# Only set using env var as of June 2025
|
|
@@ -100,59 +119,59 @@ module Datadog
|
|
|
100
119
|
),
|
|
101
120
|
|
|
102
121
|
# 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
|
|
122
|
+
conf_value('DD_AGENT_TRANSPORT', agent_transport(agent_settings), seq_id, 'unknown'), # rubocop:disable CustomCops/EnvStringValidationCop
|
|
104
123
|
|
|
105
124
|
# writer_options is defined as an option that has a Hash value.
|
|
106
125
|
conf_value(
|
|
107
126
|
'tracing.writer_options.buffer_size',
|
|
108
|
-
to_value(
|
|
127
|
+
to_value(settings.tracing.writer_options[:buffer_size]),
|
|
109
128
|
seq_id,
|
|
110
129
|
writer_option_origin
|
|
111
130
|
),
|
|
112
131
|
conf_value(
|
|
113
132
|
'tracing.writer_options.flush_interval',
|
|
114
|
-
to_value(
|
|
133
|
+
to_value(settings.tracing.writer_options[:flush_interval]),
|
|
115
134
|
seq_id,
|
|
116
135
|
writer_option_origin
|
|
117
136
|
),
|
|
118
137
|
|
|
119
|
-
conf_value('DD_AGENT_HOST',
|
|
138
|
+
conf_value('DD_AGENT_HOST', settings.agent.host, seq_id, get_telemetry_origin(settings, 'agent.host')),
|
|
120
139
|
conf_value(
|
|
121
140
|
'DD_TRACE_SAMPLE_RATE',
|
|
122
|
-
to_value(
|
|
141
|
+
to_value(settings.tracing.sampling.default_rate),
|
|
123
142
|
seq_id,
|
|
124
|
-
get_telemetry_origin(
|
|
143
|
+
get_telemetry_origin(settings, 'tracing.sampling.default_rate')
|
|
125
144
|
),
|
|
126
145
|
conf_value(
|
|
127
146
|
'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
|
|
128
|
-
|
|
147
|
+
settings.tracing.contrib.global_default_service_name.enabled,
|
|
129
148
|
seq_id,
|
|
130
|
-
get_telemetry_origin(
|
|
149
|
+
get_telemetry_origin(settings, 'tracing.contrib.global_default_service_name.enabled')
|
|
131
150
|
),
|
|
132
151
|
conf_value(
|
|
133
152
|
'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED',
|
|
134
|
-
|
|
153
|
+
settings.tracing.contrib.peer_service_defaults,
|
|
135
154
|
seq_id,
|
|
136
|
-
get_telemetry_origin(
|
|
155
|
+
get_telemetry_origin(settings, 'tracing.contrib.peer_service_defaults')
|
|
137
156
|
),
|
|
138
157
|
conf_value(
|
|
139
158
|
'DD_TRACE_DEBUG',
|
|
140
|
-
|
|
159
|
+
settings.diagnostics.debug,
|
|
141
160
|
seq_id,
|
|
142
|
-
get_telemetry_origin(
|
|
161
|
+
get_telemetry_origin(settings, 'diagnostics.debug')
|
|
143
162
|
)
|
|
144
163
|
]
|
|
145
164
|
|
|
146
165
|
peer_service_mapping_str = ''
|
|
147
|
-
unless
|
|
148
|
-
peer_service_mapping =
|
|
166
|
+
unless settings.tracing.contrib.peer_service_mapping.empty?
|
|
167
|
+
peer_service_mapping = settings.tracing.contrib.peer_service_mapping
|
|
149
168
|
peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
|
|
150
169
|
end
|
|
151
170
|
list << conf_value(
|
|
152
171
|
'DD_TRACE_PEER_SERVICE_MAPPING',
|
|
153
172
|
peer_service_mapping_str,
|
|
154
173
|
seq_id,
|
|
155
|
-
get_telemetry_origin(
|
|
174
|
+
get_telemetry_origin(settings, 'tracing.contrib.peer_service_mapping')
|
|
156
175
|
)
|
|
157
176
|
|
|
158
177
|
# Whitelist of configuration options to send in additional payload object
|
|
@@ -160,9 +179,9 @@ module Datadog
|
|
|
160
179
|
split_option = option_path.split('.')
|
|
161
180
|
list << conf_value(
|
|
162
181
|
option_path,
|
|
163
|
-
to_value(
|
|
182
|
+
to_value(settings.dig(*split_option)),
|
|
164
183
|
seq_id,
|
|
165
|
-
get_telemetry_origin(
|
|
184
|
+
get_telemetry_origin(settings, option_path)
|
|
166
185
|
)
|
|
167
186
|
end
|
|
168
187
|
|
|
@@ -181,34 +200,34 @@ module Datadog
|
|
|
181
200
|
)
|
|
182
201
|
|
|
183
202
|
# Add some more custom additional payload values here
|
|
184
|
-
if
|
|
203
|
+
if settings.logger.instance
|
|
185
204
|
list << conf_value(
|
|
186
205
|
'logger.instance',
|
|
187
|
-
|
|
206
|
+
settings.logger.instance.class.to_s,
|
|
188
207
|
seq_id,
|
|
189
|
-
get_telemetry_origin(
|
|
208
|
+
get_telemetry_origin(settings, 'logger.instance')
|
|
190
209
|
)
|
|
191
210
|
end
|
|
192
|
-
if
|
|
211
|
+
if settings.respond_to?('appsec')
|
|
193
212
|
list << conf_value(
|
|
194
213
|
'appsec.enabled',
|
|
195
|
-
|
|
214
|
+
settings.dig('appsec', 'enabled'),
|
|
196
215
|
seq_id,
|
|
197
|
-
get_telemetry_origin(
|
|
216
|
+
get_telemetry_origin(settings, 'appsec.enabled')
|
|
198
217
|
)
|
|
199
218
|
list << conf_value(
|
|
200
219
|
'appsec.sca_enabled',
|
|
201
|
-
|
|
220
|
+
settings.dig('appsec', 'sca_enabled'),
|
|
202
221
|
seq_id,
|
|
203
|
-
get_telemetry_origin(
|
|
222
|
+
get_telemetry_origin(settings, 'appsec.sca_enabled')
|
|
204
223
|
)
|
|
205
224
|
end
|
|
206
|
-
if
|
|
225
|
+
if settings.respond_to?('ci')
|
|
207
226
|
list << conf_value(
|
|
208
227
|
'ci.enabled',
|
|
209
|
-
|
|
228
|
+
settings.dig('ci', 'enabled'),
|
|
210
229
|
seq_id,
|
|
211
|
-
get_telemetry_origin(
|
|
230
|
+
get_telemetry_origin(settings, 'ci.enabled')
|
|
212
231
|
)
|
|
213
232
|
end
|
|
214
233
|
|
|
@@ -218,8 +237,8 @@ module Datadog
|
|
|
218
237
|
# standard:enable Metrics/AbcSize
|
|
219
238
|
# standard:enable Metrics/MethodLength
|
|
220
239
|
|
|
221
|
-
def agent_transport
|
|
222
|
-
adapter =
|
|
240
|
+
def agent_transport(agent_settings)
|
|
241
|
+
adapter = agent_settings.adapter
|
|
223
242
|
if adapter == Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
|
|
224
243
|
'UDS'
|
|
225
244
|
else
|
|
@@ -260,23 +279,22 @@ module Datadog
|
|
|
260
279
|
end
|
|
261
280
|
end
|
|
262
281
|
|
|
263
|
-
def install_signature
|
|
264
|
-
config = Datadog.configuration
|
|
282
|
+
def install_signature(settings)
|
|
265
283
|
{
|
|
266
|
-
install_id:
|
|
267
|
-
install_type:
|
|
268
|
-
install_time:
|
|
284
|
+
install_id: settings.dig('telemetry', 'install_id'),
|
|
285
|
+
install_type: settings.dig('telemetry', 'install_type'),
|
|
286
|
+
install_time: settings.dig('telemetry', 'install_time'),
|
|
269
287
|
}
|
|
270
288
|
end
|
|
271
289
|
|
|
272
|
-
def get_telemetry_origin(
|
|
290
|
+
def get_telemetry_origin(settings, config_path)
|
|
273
291
|
split_option = config_path.split('.')
|
|
274
292
|
option_name = split_option.pop
|
|
275
293
|
return 'unknown' if option_name.nil?
|
|
276
294
|
|
|
277
295
|
# @type var parent_setting: Core::Configuration::Options
|
|
278
296
|
# @type var option: Core::Configuration::Option
|
|
279
|
-
parent_setting =
|
|
297
|
+
parent_setting = settings.dig(*split_option)
|
|
280
298
|
option = parent_setting.send(:resolve_option, option_name.to_sym)
|
|
281
299
|
option.precedence_set&.origin || 'unknown'
|
|
282
300
|
end
|
|
@@ -28,13 +28,36 @@ module Datadog
|
|
|
28
28
|
# and app-closing events.
|
|
29
29
|
class SynthAppClientConfigurationChange < AppStarted
|
|
30
30
|
def type
|
|
31
|
-
|
|
31
|
+
if reset?
|
|
32
|
+
super
|
|
33
|
+
else
|
|
34
|
+
'app-client-configuration-change'
|
|
35
|
+
end
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
def payload
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
if reset?
|
|
40
|
+
super
|
|
41
|
+
else
|
|
42
|
+
{
|
|
43
|
+
configuration: @configuration,
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def app_started?
|
|
49
|
+
reset?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Revert this event to a "regular" AppStarted event.
|
|
53
|
+
#
|
|
54
|
+
# Used in after_fork to send the AppStarted event in child processes.
|
|
55
|
+
def reset!
|
|
56
|
+
@reset = true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def reset?
|
|
60
|
+
!!@reset
|
|
38
61
|
end
|
|
39
62
|
end
|
|
40
63
|
end
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
require_relative '../../../transport/http/api/endpoint'
|
|
4
4
|
require_relative '../../../transport/http/api/instance'
|
|
5
5
|
require_relative '../../../transport/http/api/spec'
|
|
6
|
+
require_relative '../../../transport/http/client'
|
|
6
7
|
require_relative '../../../transport/request'
|
|
7
|
-
require_relative 'client'
|
|
8
8
|
|
|
9
9
|
module Datadog
|
|
10
10
|
module Core
|
|
@@ -12,10 +12,11 @@ module Datadog
|
|
|
12
12
|
module Transport
|
|
13
13
|
module HTTP
|
|
14
14
|
module Telemetry
|
|
15
|
-
|
|
15
|
+
class Client < Core::Transport::HTTP::Client
|
|
16
16
|
def send_telemetry_payload(request)
|
|
17
|
-
send_request(request) do |api, env|
|
|
18
|
-
api
|
|
17
|
+
send_request(request) do |api, env|
|
|
18
|
+
# TODO how to make api have the derived type for steep?
|
|
19
|
+
api.send_telemetry(env) # steep:ignore
|
|
19
20
|
end
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -83,8 +84,6 @@ module Datadog
|
|
|
83
84
|
end
|
|
84
85
|
end
|
|
85
86
|
end
|
|
86
|
-
|
|
87
|
-
HTTP::Client.include(Telemetry::Client)
|
|
88
87
|
end
|
|
89
88
|
end
|
|
90
89
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../../transport/parcel'
|
|
4
|
-
require_relative 'http/client'
|
|
5
4
|
require_relative 'http/telemetry'
|
|
6
5
|
|
|
7
6
|
module Datadog
|
|
@@ -32,7 +31,7 @@ module Datadog
|
|
|
32
31
|
@apis = apis
|
|
33
32
|
@logger = logger
|
|
34
33
|
|
|
35
|
-
@client = HTTP::Client.new(@apis[default_api], logger: logger)
|
|
34
|
+
@client = Core::Telemetry::Transport::HTTP::Telemetry::Client.new(@apis[default_api], logger: logger)
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
def send_telemetry(request_type:, payload:)
|
|
@@ -9,7 +9,10 @@ require_relative '../workers/queue'
|
|
|
9
9
|
module Datadog
|
|
10
10
|
module Core
|
|
11
11
|
module Telemetry
|
|
12
|
-
# Accumulates events and sends them to the API at a regular interval,
|
|
12
|
+
# Accumulates events and sends them to the API at a regular interval,
|
|
13
|
+
# including heartbeat event.
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
13
16
|
class Worker
|
|
14
17
|
include Core::Workers::Queue
|
|
15
18
|
include Core::Workers::Polling
|
|
@@ -40,11 +43,15 @@ module Datadog
|
|
|
40
43
|
self.enabled = enabled
|
|
41
44
|
# Workers::IntervalLoop settings
|
|
42
45
|
self.loop_base_interval = metrics_aggregation_interval_seconds
|
|
43
|
-
self.fork_policy = Core::Workers::Async::Thread::
|
|
46
|
+
self.fork_policy = Core::Workers::Async::Thread::FORK_POLICY_RESTART
|
|
44
47
|
|
|
45
48
|
@shutdown_timeout = shutdown_timeout
|
|
46
49
|
@buffer_size = buffer_size
|
|
47
50
|
|
|
51
|
+
initialize_state
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private def initialize_state
|
|
48
55
|
self.buffer = buffer_klass.new(@buffer_size)
|
|
49
56
|
|
|
50
57
|
@initial_event_once = Utils::OnlyOnceSuccessful.new(APP_STARTED_EVENT_RETRIES)
|
|
@@ -53,12 +60,13 @@ module Datadog
|
|
|
53
60
|
attr_reader :logger
|
|
54
61
|
attr_reader :initial_event_once
|
|
55
62
|
attr_reader :initial_event
|
|
63
|
+
attr_reader :emitter
|
|
56
64
|
|
|
57
65
|
# Returns true if worker thread is successfully started,
|
|
58
66
|
# false if worker thread was not started but telemetry is enabled,
|
|
59
67
|
# nil if telemetry is disabled.
|
|
60
68
|
def start(initial_event)
|
|
61
|
-
return
|
|
69
|
+
return unless enabled?
|
|
62
70
|
|
|
63
71
|
@initial_event = initial_event
|
|
64
72
|
|
|
@@ -79,7 +87,21 @@ module Datadog
|
|
|
79
87
|
# for not enqueueing event (presently) is that telemetry is disabled
|
|
80
88
|
# altogether, and in this case other methods return nil.
|
|
81
89
|
def enqueue(event)
|
|
82
|
-
return
|
|
90
|
+
return unless enabled?
|
|
91
|
+
|
|
92
|
+
# Start the worker if needed, including in forked children.
|
|
93
|
+
# Needs to be done before pushing to buffer since perform
|
|
94
|
+
# may invoke after_fork handler which resets the buffer.
|
|
95
|
+
#
|
|
96
|
+
# Telemetry is special in that it permits events to be submitted
|
|
97
|
+
# to the worker with the worker not running, and the worker is
|
|
98
|
+
# explicitly started later (to maintain proper initialization order).
|
|
99
|
+
# Thus here we can't just call perform unconditionally and must
|
|
100
|
+
# check if the worker is supposed to be running, and only call
|
|
101
|
+
# perform in that case.
|
|
102
|
+
if worker && !worker.alive?
|
|
103
|
+
perform
|
|
104
|
+
end
|
|
83
105
|
|
|
84
106
|
buffer.push(event)
|
|
85
107
|
true
|
|
@@ -133,7 +155,7 @@ module Datadog
|
|
|
133
155
|
private
|
|
134
156
|
|
|
135
157
|
def perform(*events)
|
|
136
|
-
return
|
|
158
|
+
return unless enabled?
|
|
137
159
|
|
|
138
160
|
if need_initial_event?
|
|
139
161
|
started!
|
|
@@ -189,7 +211,9 @@ module Datadog
|
|
|
189
211
|
# dependencies and send the new ones.
|
|
190
212
|
# System tests demand only one instance of this event per
|
|
191
213
|
# dependency.
|
|
192
|
-
|
|
214
|
+
if @dependency_collection && initial_event.app_started?
|
|
215
|
+
send_event(Event::AppDependenciesLoaded.new)
|
|
216
|
+
end
|
|
193
217
|
|
|
194
218
|
true
|
|
195
219
|
else
|
|
@@ -240,6 +264,27 @@ module Datadog
|
|
|
240
264
|
disable!
|
|
241
265
|
end
|
|
242
266
|
|
|
267
|
+
# Stop the worker after fork without sending closing event.
|
|
268
|
+
# The closing event will be (or should be) sent by the worker
|
|
269
|
+
# in the parent process.
|
|
270
|
+
# Also, discard any accumulated events since they will be sent by
|
|
271
|
+
# the parent.
|
|
272
|
+
def after_fork
|
|
273
|
+
# If telemetry is disabled, we still reset the state to avoid
|
|
274
|
+
# having wrong state. It is possible that in the future telemetry
|
|
275
|
+
# will be re-enabled after errors.
|
|
276
|
+
initialize_state
|
|
277
|
+
# In the child process, we get a new runtime_id.
|
|
278
|
+
# As such we need to send AppStarted event.
|
|
279
|
+
# In the parent process, the event may have been the
|
|
280
|
+
# SynthAppClientConfigurationChange instead of AppStarted,
|
|
281
|
+
# and in that case we need to convert it to the "regular"
|
|
282
|
+
# AppStarted event.
|
|
283
|
+
if @initial_event.is_a?(Event::SynthAppClientConfigurationChange)
|
|
284
|
+
@initial_event.reset! # steep:ignore
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
243
288
|
# Deduplicate logs by counting the number of repeated occurrences of the same log
|
|
244
289
|
# entry and replacing them with a single entry with the calculated `count` value.
|
|
245
290
|
# Non-log events are unchanged.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'env'
|
|
4
|
+
require_relative '../response'
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module Core
|
|
8
|
+
module Transport
|
|
9
|
+
module HTTP
|
|
10
|
+
# Routes, encodes, and sends DI data to the trace agent via HTTP.
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
class Client
|
|
14
|
+
attr_reader :api, :logger
|
|
15
|
+
|
|
16
|
+
def initialize(api, logger:)
|
|
17
|
+
@api = api
|
|
18
|
+
@logger = logger
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def send_request(request, &block)
|
|
24
|
+
# Build request into env
|
|
25
|
+
env = build_env(request)
|
|
26
|
+
|
|
27
|
+
# Get responses from API
|
|
28
|
+
yield(api, env).tap do |response|
|
|
29
|
+
on_response(response)
|
|
30
|
+
end
|
|
31
|
+
rescue => exception
|
|
32
|
+
on_exception(exception)
|
|
33
|
+
|
|
34
|
+
Datadog::Core::Transport::InternalErrorResponse.new(exception)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def build_env(request)
|
|
38
|
+
Datadog::Core::Transport::HTTP::Env.new(request)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Callback that is invoked if a request did not raise an exception
|
|
42
|
+
# (but did not necessarily complete successfully).
|
|
43
|
+
#
|
|
44
|
+
# Override in subclasses.
|
|
45
|
+
#
|
|
46
|
+
# Note that the client will return the original response -
|
|
47
|
+
# the return value of this method is ignored, and response should
|
|
48
|
+
# not be modified.
|
|
49
|
+
def on_response(response)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Callback that is invoked if a request failed with an exception.
|
|
53
|
+
#
|
|
54
|
+
# Override in subclasses.
|
|
55
|
+
def on_exception(exception)
|
|
56
|
+
message = build_exception_message(exception)
|
|
57
|
+
|
|
58
|
+
logger.debug(message)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def build_exception_message(exception)
|
|
62
|
+
"Internal error during #{self.class.name} request. Cause: #{exception.class}: #{exception} " \
|
|
63
|
+
"Location: #{Array(exception.backtrace).first}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -29,7 +29,11 @@ module Datadog
|
|
|
29
29
|
# In https://github.com/DataDog/dd-trace-rb/pull/1398#issuecomment-797378810 we have a discussion of alternatives,
|
|
30
30
|
# including an alternative implementation that is Ractor-safe once spent.
|
|
31
31
|
class OnlyOnceSuccessful < OnlyOnce
|
|
32
|
-
def initialize(limit =
|
|
32
|
+
def initialize(limit = nil)
|
|
33
|
+
if limit && limit <= 0
|
|
34
|
+
raise ArgumentError, "Limit must be a positive integer if provided: #{limit}"
|
|
35
|
+
end
|
|
36
|
+
|
|
33
37
|
super()
|
|
34
38
|
|
|
35
39
|
@limit = limit
|
|
@@ -71,7 +75,7 @@ module Datadog
|
|
|
71
75
|
end
|
|
72
76
|
|
|
73
77
|
def limited?
|
|
74
|
-
!@limit.nil?
|
|
78
|
+
!@limit.nil?
|
|
75
79
|
end
|
|
76
80
|
|
|
77
81
|
def reset_ran_once_state_for_tests
|