cw-datadog 2.23.0.2 → 2.23.0.4
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 +412 -25
- data/lib/datadog/core/cloudwise/component.rb +195 -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 +90 -4
- 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 +43 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +6 -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 +73 -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
|
@@ -19,6 +19,22 @@ module Datadog
|
|
|
19
19
|
# 成功的状态码
|
|
20
20
|
CODE_SUCCESS = 1000
|
|
21
21
|
|
|
22
|
+
# 熔断状态定义
|
|
23
|
+
FUSE_STATE_NORMAL = 0 # 正常
|
|
24
|
+
FUSE_STATE_FUSING = 1 # 熔断
|
|
25
|
+
|
|
26
|
+
# 熔断描述定义
|
|
27
|
+
FUSE_DESCRIBE_LICENSE_EXPIRED = 7 # License过期熔断
|
|
28
|
+
FUSE_DESCRIBE_AGENT_SUSPENDED = 8 # Agent暂停熔断
|
|
29
|
+
FUSE_DESCRIBE_LICENSE_OVER_QUOTA = 9 # License超配额熔断
|
|
30
|
+
FUSE_DESCRIBE_LICENSE_INTERFACE_ERROR = 10 # License接口异常熔断
|
|
31
|
+
|
|
32
|
+
# License 响应码定义
|
|
33
|
+
LICENSE_CODE_AGENT_SUSPENDED = 4113 # Agent暂停
|
|
34
|
+
LICENSE_CODE_OVER_QUOTA = 4114 # License超配额
|
|
35
|
+
LICENSE_CODE_EXPIRED = 4116 # License过期
|
|
36
|
+
LICENSE_CODE_INTERFACE_ERROR = 4120 # License接口异常
|
|
37
|
+
|
|
22
38
|
attr_reader :client
|
|
23
39
|
|
|
24
40
|
def initialize(client:, logger:, probe_state:, **options)
|
|
@@ -26,6 +42,8 @@ module Datadog
|
|
|
26
42
|
@logger = logger
|
|
27
43
|
@probe_state = probe_state
|
|
28
44
|
@failure_count = 0
|
|
45
|
+
@last_fuse_state = nil # 记录最后一次的熔断状态
|
|
46
|
+
@last_fuse_describe = nil # 记录最后一次的熔断描述
|
|
29
47
|
|
|
30
48
|
# Workers::Async::Thread settings
|
|
31
49
|
self.fork_policy = options.fetch(:fork_policy, Workers::Async::Thread::FORK_POLICY_STOP)
|
|
@@ -76,20 +94,37 @@ module Datadog
|
|
|
76
94
|
end
|
|
77
95
|
|
|
78
96
|
code = result[:code]
|
|
97
|
+
# msg 字段在响应的顶层(result[:message]),是字符串 "true" 或 "false"
|
|
98
|
+
msg = result[:message]
|
|
79
99
|
|
|
80
|
-
# License 校验成功 (code == 1000)
|
|
81
|
-
if code == CODE_SUCCESS
|
|
100
|
+
# License 校验成功 (code == 1000 且 msg == 'true')
|
|
101
|
+
if code == CODE_SUCCESS && msg == 'true'
|
|
82
102
|
Cloudwise.log_debug { 'Cloudwise: License valid' }
|
|
83
103
|
probe_state.mark_license_valid!
|
|
84
104
|
@failure_count = 0 # 重置失败计数
|
|
105
|
+
# 上报正常状态(如果状态发生变化)
|
|
106
|
+
report_fuse_state_if_changed(FUSE_STATE_NORMAL, nil)
|
|
107
|
+
return
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# 特殊情况:code == 1000 但 msg == 'false',视为 License 过期
|
|
111
|
+
if code == CODE_SUCCESS && msg == 'false'
|
|
112
|
+
Cloudwise.log_error { "Cloudwise: License verification failed - code #{code} with msg false (License expired)" }
|
|
113
|
+
probe_state.mark_license_invalid!
|
|
114
|
+
@failure_count = 0 # 重置失败计数(因为接口成功返回了)
|
|
115
|
+
# 上报为License过期熔断状态
|
|
116
|
+
report_fuse_state_if_changed(FUSE_STATE_FUSING, FUSE_DESCRIBE_LICENSE_EXPIRED)
|
|
85
117
|
return
|
|
86
118
|
end
|
|
87
119
|
|
|
88
|
-
# License
|
|
120
|
+
# 其他 License 校验失败情况 (code != 1000)
|
|
89
121
|
Cloudwise.log_error { "Cloudwise: License verification failed with code #{code}" }
|
|
90
|
-
Cloudwise.log_error { "Cloudwise: Data collection suspended due to invalid license" }
|
|
91
122
|
probe_state.mark_license_invalid!
|
|
92
123
|
@failure_count = 0 # 重置失败计数(因为接口成功返回了)
|
|
124
|
+
|
|
125
|
+
# 根据错误码上报相应的熔断状态
|
|
126
|
+
fuse_describe = map_license_code_to_fuse_describe(code)
|
|
127
|
+
report_fuse_state_if_changed(FUSE_STATE_FUSING, fuse_describe)
|
|
93
128
|
end
|
|
94
129
|
|
|
95
130
|
def handle_license_failure
|
|
@@ -100,8 +135,59 @@ module Datadog
|
|
|
100
135
|
if @failure_count >= MAX_RETRIES
|
|
101
136
|
Cloudwise.log_error { "Cloudwise: License verification failed #{@failure_count} times, marking as invalid" }
|
|
102
137
|
probe_state.mark_license_invalid!
|
|
138
|
+
|
|
139
|
+
# 上报License接口异常熔断状态
|
|
140
|
+
report_fuse_state_if_changed(FUSE_STATE_FUSING, FUSE_DESCRIBE_LICENSE_INTERFACE_ERROR)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# 将License错误码映射为熔断描述
|
|
145
|
+
def map_license_code_to_fuse_describe(license_code)
|
|
146
|
+
case license_code
|
|
147
|
+
when LICENSE_CODE_AGENT_SUSPENDED
|
|
148
|
+
FUSE_DESCRIBE_AGENT_SUSPENDED
|
|
149
|
+
when LICENSE_CODE_OVER_QUOTA
|
|
150
|
+
FUSE_DESCRIBE_LICENSE_OVER_QUOTA
|
|
151
|
+
when LICENSE_CODE_EXPIRED
|
|
152
|
+
FUSE_DESCRIBE_LICENSE_EXPIRED
|
|
153
|
+
when LICENSE_CODE_INTERFACE_ERROR
|
|
154
|
+
FUSE_DESCRIBE_LICENSE_INTERFACE_ERROR
|
|
155
|
+
else
|
|
156
|
+
# 其他未知的License错误码,统一按接口异常处理
|
|
157
|
+
FUSE_DESCRIBE_LICENSE_INTERFACE_ERROR
|
|
103
158
|
end
|
|
104
159
|
end
|
|
160
|
+
|
|
161
|
+
# 仅在状态发生变化时上报熔断状态
|
|
162
|
+
# @param fuse_state [Integer] 熔断状态: 0-正常, 1-熔断
|
|
163
|
+
# @param fuse_describe [Integer, nil] 熔断描述: 7/8/9/10,正常状态时为nil
|
|
164
|
+
def report_fuse_state_if_changed(fuse_state, fuse_describe)
|
|
165
|
+
# 检查状态是否发生变化
|
|
166
|
+
if @last_fuse_state == fuse_state && @last_fuse_describe == fuse_describe
|
|
167
|
+
Cloudwise.log_debug { "Cloudwise: Fuse state unchanged (state: #{fuse_state}, describe: #{fuse_describe}), skip reporting" }
|
|
168
|
+
return
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# 状态发生变化,进行上报
|
|
172
|
+
Cloudwise.log_info { "Cloudwise: Fuse state changed from (#{@last_fuse_state}, #{@last_fuse_describe}) to (#{fuse_state}, #{fuse_describe})" }
|
|
173
|
+
|
|
174
|
+
# 构造上报参数
|
|
175
|
+
fuse_describe_str = fuse_describe ? fuse_describe.to_s : fuse_state.to_s
|
|
176
|
+
|
|
177
|
+
# 调用Client的上报接口
|
|
178
|
+
result = client.report_fuse_state(fuse_state: fuse_state, fuse_describe: fuse_describe_str)
|
|
179
|
+
|
|
180
|
+
if result[:success]
|
|
181
|
+
Cloudwise.log_debug { "Cloudwise: Fuse state reported successfully (state: #{fuse_state}, describe: #{fuse_describe})" }
|
|
182
|
+
# 更新最后一次的状态
|
|
183
|
+
@last_fuse_state = fuse_state
|
|
184
|
+
@last_fuse_describe = fuse_describe
|
|
185
|
+
else
|
|
186
|
+
Cloudwise.log_error { "Cloudwise: Failed to report fuse state: #{result[:error]}" }
|
|
187
|
+
end
|
|
188
|
+
rescue => e
|
|
189
|
+
Cloudwise.log_error { "Cloudwise: Error reporting fuse state: #{e.class.name} #{e.message}" }
|
|
190
|
+
end
|
|
105
191
|
end
|
|
106
192
|
end
|
|
107
193
|
end
|
|
@@ -15,6 +15,12 @@ module Datadog
|
|
|
15
15
|
@heartbeat_active = false # 心跳是否正常
|
|
16
16
|
@license_valid = false # License 是否校验通过
|
|
17
17
|
@app_registered = false # 应用是否已注册(注册失败不影响采集)
|
|
18
|
+
|
|
19
|
+
# 融合模式状态
|
|
20
|
+
@docc_registered = false # 注册是否成功
|
|
21
|
+
@docc_heartbeat_active = false # 心跳是否正常
|
|
22
|
+
@docc_operation_active = true # 操作状态(默认为 true,agent_stop 时为 false)
|
|
23
|
+
@use_docc_mode = false # 是否使用 模式
|
|
18
24
|
end
|
|
19
25
|
|
|
20
26
|
# Host ID 相关
|
|
@@ -91,10 +97,81 @@ module Datadog
|
|
|
91
97
|
end
|
|
92
98
|
end
|
|
93
99
|
|
|
94
|
-
#
|
|
100
|
+
# DOCC 注册相关
|
|
101
|
+
def mark_docc_registered!
|
|
102
|
+
@mutex.synchronize do
|
|
103
|
+
return if @docc_registered
|
|
104
|
+
@docc_registered = true
|
|
105
|
+
Cloudwise.log_debug { 'Cloudwise DOCC: Extension registered' }
|
|
106
|
+
log_status_change
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def mark_docc_unregistered!
|
|
111
|
+
@mutex.synchronize do
|
|
112
|
+
return unless @docc_registered
|
|
113
|
+
@docc_registered = false
|
|
114
|
+
Cloudwise.log_warn { 'Cloudwise DOCC: Extension not registered' }
|
|
115
|
+
log_status_change
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# DOCC 心跳相关
|
|
120
|
+
def mark_docc_heartbeat_active!
|
|
121
|
+
@mutex.synchronize do
|
|
122
|
+
return if @docc_heartbeat_active
|
|
123
|
+
@docc_heartbeat_active = true
|
|
124
|
+
Cloudwise.log_debug { 'Cloudwise DOCC: Heartbeat active' }
|
|
125
|
+
log_status_change
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def mark_docc_heartbeat_inactive!
|
|
130
|
+
@mutex.synchronize do
|
|
131
|
+
return unless @docc_heartbeat_active
|
|
132
|
+
@docc_heartbeat_active = false
|
|
133
|
+
Cloudwise.log_warn { 'Cloudwise DOCC: Heartbeat inactive' }
|
|
134
|
+
log_status_change
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# DOCC 操作相关
|
|
139
|
+
def mark_docc_operation_active!
|
|
140
|
+
@mutex.synchronize do
|
|
141
|
+
return if @docc_operation_active
|
|
142
|
+
@docc_operation_active = true
|
|
143
|
+
Cloudwise.log_info { 'Cloudwise DOCC: Agent started - data collection enabled' }
|
|
144
|
+
log_status_change
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def mark_docc_operation_inactive!
|
|
149
|
+
@mutex.synchronize do
|
|
150
|
+
return unless @docc_operation_active
|
|
151
|
+
@docc_operation_active = false
|
|
152
|
+
Cloudwise.log_info { 'Cloudwise DOCC: Agent stopped - data collection disabled' }
|
|
153
|
+
log_status_change
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# 设置使用 DOCC 模式
|
|
158
|
+
def enable_docc_mode!
|
|
159
|
+
@mutex.synchronize do
|
|
160
|
+
@use_docc_mode = true
|
|
161
|
+
Cloudwise.log_debug { 'Cloudwise: Using DOCC integrated mode' }
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# 探针是否可以采集数据
|
|
166
|
+
# 如果使用 DOCC 模式:需要 DOCC 心跳 + License + Operation 都正常
|
|
167
|
+
# 如果使用传统模式:需要 Host ID + 心跳 + License 都正常
|
|
95
168
|
def can_collect_data?
|
|
96
169
|
@mutex.synchronize do
|
|
97
|
-
|
|
170
|
+
if @use_docc_mode
|
|
171
|
+
@docc_heartbeat_active && @license_valid && @docc_operation_active
|
|
172
|
+
else
|
|
173
|
+
@host_id_ready && @heartbeat_active && @license_valid
|
|
174
|
+
end
|
|
98
175
|
end
|
|
99
176
|
end
|
|
100
177
|
|
|
@@ -115,6 +192,22 @@ module Datadog
|
|
|
115
192
|
@mutex.synchronize { @app_registered }
|
|
116
193
|
end
|
|
117
194
|
|
|
195
|
+
def docc_registered?
|
|
196
|
+
@mutex.synchronize { @docc_registered }
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def docc_heartbeat_active?
|
|
200
|
+
@mutex.synchronize { @docc_heartbeat_active }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def docc_operation_active?
|
|
204
|
+
@mutex.synchronize { @docc_operation_active }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def using_docc_mode?
|
|
208
|
+
@mutex.synchronize { @use_docc_mode }
|
|
209
|
+
end
|
|
210
|
+
|
|
118
211
|
# 兼容旧接口
|
|
119
212
|
def suspended?
|
|
120
213
|
!can_collect_data?
|
|
@@ -127,13 +220,27 @@ module Datadog
|
|
|
127
220
|
# 获取当前状态摘要
|
|
128
221
|
def status
|
|
129
222
|
@mutex.synchronize do
|
|
130
|
-
{
|
|
223
|
+
base_status = {
|
|
131
224
|
host_id_ready: @host_id_ready,
|
|
132
225
|
heartbeat_active: @heartbeat_active,
|
|
133
226
|
license_valid: @license_valid,
|
|
134
|
-
app_registered: @app_registered
|
|
135
|
-
can_collect_data: @host_id_ready && @heartbeat_active && @license_valid
|
|
227
|
+
app_registered: @app_registered
|
|
136
228
|
}
|
|
229
|
+
|
|
230
|
+
if @use_docc_mode
|
|
231
|
+
base_status.merge(
|
|
232
|
+
use_docc_mode: true,
|
|
233
|
+
docc_registered: @docc_registered,
|
|
234
|
+
docc_heartbeat_active: @docc_heartbeat_active,
|
|
235
|
+
docc_operation_active: @docc_operation_active,
|
|
236
|
+
can_collect_data: @docc_heartbeat_active && @license_valid && @docc_operation_active
|
|
237
|
+
)
|
|
238
|
+
else
|
|
239
|
+
base_status.merge(
|
|
240
|
+
use_docc_mode: false,
|
|
241
|
+
can_collect_data: @host_id_ready && @heartbeat_active && @license_valid
|
|
242
|
+
)
|
|
243
|
+
end
|
|
137
244
|
end
|
|
138
245
|
end
|
|
139
246
|
|
|
@@ -143,15 +250,30 @@ module Datadog
|
|
|
143
250
|
# 它不能再次获取锁,所以直接读取实例变量
|
|
144
251
|
def log_status_change
|
|
145
252
|
# 直接读取实例变量,避免递归锁定(不调用 can_collect_data? 方法)
|
|
146
|
-
if @
|
|
147
|
-
|
|
253
|
+
if @use_docc_mode
|
|
254
|
+
# DOCC 模式状态日志
|
|
255
|
+
if @docc_heartbeat_active && @license_valid && @docc_operation_active
|
|
256
|
+
Cloudwise.log_debug { 'Cloudwise DOCC: Probe ACTIVE - data collection enabled' }
|
|
257
|
+
else
|
|
258
|
+
reasons = []
|
|
259
|
+
reasons << 'DOCC Heartbeat inactive' unless @docc_heartbeat_active
|
|
260
|
+
reasons << 'License invalid' unless @license_valid
|
|
261
|
+
reasons << 'Agent stopped by operation' unless @docc_operation_active
|
|
262
|
+
|
|
263
|
+
Cloudwise.log_debug { "Cloudwise DOCC: Probe SUSPENDED - data collection disabled (#{reasons.join(', ')})" }
|
|
264
|
+
end
|
|
148
265
|
else
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
266
|
+
# 传统模式状态日志
|
|
267
|
+
if @host_id_ready && @heartbeat_active && @license_valid
|
|
268
|
+
Cloudwise.log_debug { 'Cloudwise: Probe ACTIVE - data collection enabled' }
|
|
269
|
+
else
|
|
270
|
+
reasons = []
|
|
271
|
+
reasons << 'Host ID not ready' unless @host_id_ready
|
|
272
|
+
reasons << 'Heartbeat inactive' unless @heartbeat_active
|
|
273
|
+
reasons << 'License invalid' unless @license_valid
|
|
153
274
|
|
|
154
|
-
|
|
275
|
+
Cloudwise.log_debug { "Cloudwise: Probe SUSPENDED - data collection disabled (#{reasons.join(', ')})" }
|
|
276
|
+
end
|
|
155
277
|
end
|
|
156
278
|
end
|
|
157
279
|
end
|
|
@@ -15,6 +15,7 @@ require_relative '../../tracing/component'
|
|
|
15
15
|
require_relative '../../profiling/component'
|
|
16
16
|
require_relative '../../appsec/component'
|
|
17
17
|
require_relative '../../di/component'
|
|
18
|
+
require_relative '../../open_feature/component'
|
|
18
19
|
require_relative '../../error_tracking/component'
|
|
19
20
|
require_relative '../crashtracking/component'
|
|
20
21
|
require_relative '../environment/agent_info'
|
|
@@ -151,6 +152,7 @@ module Datadog
|
|
|
151
152
|
attr_reader \
|
|
152
153
|
:health_metrics,
|
|
153
154
|
:settings,
|
|
155
|
+
:agent_settings,
|
|
154
156
|
:logger,
|
|
155
157
|
:remote,
|
|
156
158
|
:profiler,
|
|
@@ -163,7 +165,8 @@ module Datadog
|
|
|
163
165
|
:appsec,
|
|
164
166
|
:agent_info,
|
|
165
167
|
:data_streams,
|
|
166
|
-
:cloudwise
|
|
168
|
+
:cloudwise,
|
|
169
|
+
:open_feature
|
|
167
170
|
|
|
168
171
|
def initialize(settings)
|
|
169
172
|
@settings = settings
|
|
@@ -207,7 +210,7 @@ module Datadog
|
|
|
207
210
|
# This agent_settings is intended for use within Core. If you require
|
|
208
211
|
# agent_settings within a product outside of core you should extend
|
|
209
212
|
# the Core resolver from within your product/component's namespace.
|
|
210
|
-
agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
|
|
213
|
+
@agent_settings = AgentSettingsResolver.call(settings, logger: @logger)
|
|
211
214
|
|
|
212
215
|
# Exposes agent capability information for detection by any components
|
|
213
216
|
@agent_info = Core::Environment::AgentInfo.new(agent_settings, logger: @logger)
|
|
@@ -233,6 +236,7 @@ module Datadog
|
|
|
233
236
|
@runtime_metrics = self.class.build_runtime_metrics_worker(settings, @logger, telemetry)
|
|
234
237
|
@health_metrics = self.class.build_health_metrics(settings, @logger, telemetry)
|
|
235
238
|
@appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
|
|
239
|
+
@open_feature = OpenFeature::Component.build(settings, agent_settings, logger: @logger, telemetry: telemetry)
|
|
236
240
|
@dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
|
|
237
241
|
@error_tracking = Datadog::ErrorTracking::Component.build(settings, @tracer, @logger)
|
|
238
242
|
@data_streams = self.class.build_data_streams(settings, agent_settings, @logger)
|
|
@@ -268,14 +272,8 @@ module Datadog
|
|
|
268
272
|
|
|
269
273
|
# Starts up components
|
|
270
274
|
def startup!(settings, old_state: nil)
|
|
271
|
-
# If Datadog components are not initialized yet (waiting for Cloudwise),
|
|
272
|
-
# skip startup - it will be called after Datadog components are initialized
|
|
273
|
-
unless datadog_components_initialized?
|
|
274
|
-
@pending_startup = { settings: settings, old_state: old_state }
|
|
275
|
-
return
|
|
276
|
-
end
|
|
277
275
|
|
|
278
|
-
telemetry.start(old_state&.telemetry_enabled
|
|
276
|
+
telemetry.start(old_state&.telemetry_enabled?, components: self)
|
|
279
277
|
|
|
280
278
|
if settings.profiling.enabled
|
|
281
279
|
if profiler
|
|
@@ -321,6 +319,9 @@ module Datadog
|
|
|
321
319
|
# Shutdown DI after remote, since remote config triggers DI operations.
|
|
322
320
|
dynamic_instrumentation&.shutdown!
|
|
323
321
|
|
|
322
|
+
# Shutdown OpenFeature component
|
|
323
|
+
open_feature&.shutdown!
|
|
324
|
+
|
|
324
325
|
# Decommission AppSec
|
|
325
326
|
appsec&.shutdown!
|
|
326
327
|
|
|
@@ -1025,6 +1025,49 @@ module Datadog
|
|
|
1025
1025
|
o.default nil
|
|
1026
1026
|
end
|
|
1027
1027
|
|
|
1028
|
+
# Integrated mode - whether agent handles integrated environment
|
|
1029
|
+
# @default `DD_CLOUDWISE_INTEGRATED_MODE` environment variable, otherwise `true`
|
|
1030
|
+
# @return [Boolean]
|
|
1031
|
+
option :integrated_mode do |o|
|
|
1032
|
+
o.type :bool
|
|
1033
|
+
o.env 'DD_CLOUDWISE_INTEGRATED_MODE'
|
|
1034
|
+
o.default true
|
|
1035
|
+
end
|
|
1036
|
+
|
|
1037
|
+
# Token for integrated mode (DOCC interface authentication)
|
|
1038
|
+
# Format: base64 encoded "account_id@user_id"
|
|
1039
|
+
# @default `DD_CLOUDWISE_TOKEN` environment variable
|
|
1040
|
+
# @return [String,nil]
|
|
1041
|
+
option :token do |o|
|
|
1042
|
+
o.type :string, nilable: true
|
|
1043
|
+
o.env 'DD_CLOUDWISE_TOKEN'
|
|
1044
|
+
o.default nil
|
|
1045
|
+
end
|
|
1046
|
+
|
|
1047
|
+
# API 路径前缀模式(简化配置)
|
|
1048
|
+
# 可选值: 'doop', 'apm', 'custom'
|
|
1049
|
+
# 优先级: api_prefix_mode > api_prefix > integrated_mode > 无前缀
|
|
1050
|
+
option :api_prefix_mode do |o|
|
|
1051
|
+
o.type :string, nilable: true
|
|
1052
|
+
o.env 'DD_CLOUDWISE_API_PREFIX_MODE'
|
|
1053
|
+
o.default nil
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
# API 路径前缀(自定义配置)
|
|
1057
|
+
# 优先级: api_prefix_mode > api_prefix > integrated_mode ('/apm') > 无前缀
|
|
1058
|
+
option :api_prefix do |o|
|
|
1059
|
+
o.type :string, nilable: true
|
|
1060
|
+
o.env 'DD_CLOUDWISE_API_PREFIX'
|
|
1061
|
+
o.default nil
|
|
1062
|
+
end
|
|
1063
|
+
|
|
1064
|
+
# SYS
|
|
1065
|
+
option :sys do |o|
|
|
1066
|
+
o.type :string, nilable: true
|
|
1067
|
+
o.env 'CW_SYS'
|
|
1068
|
+
o.default 'default'
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1028
1071
|
# Heartbeat interval in seconds
|
|
1029
1072
|
# @default `DD_CLOUDWISE_HEARTBEAT_INTERVAL` environment variable, otherwise `30`
|
|
1030
1073
|
# @return [Integer]
|
|
@@ -34,9 +34,11 @@ module Datadog
|
|
|
34
34
|
"DD_APPSEC_WAF_TIMEOUT" => {version: ["A"]},
|
|
35
35
|
"DD_CLOUDWISE_APP_REGISTRATION_INTERVAL" => {version: ["A"]},
|
|
36
36
|
"DD_CLOUDWISE_ENABLED" => {version: ["A"]},
|
|
37
|
-
"DD_CLOUDWISE_HEARTBEAT_INTERVAL" => {version: ["A"]},
|
|
38
|
-
"DD_CLOUDWISE_LICENSE_CHECK_INTERVAL" => {version: ["A"]},
|
|
39
37
|
"DD_CLOUDWISE_LICENSE_KEY" => {version: ["A"]},
|
|
38
|
+
"DD_CLOUDWISE_TOKEN" => {version: ["A"]},
|
|
39
|
+
"CW_SYS" => {version: ["A"]},
|
|
40
|
+
"DD_CLOUDWISE_API_PREFIX_MODE" => {version: ["A"]},
|
|
41
|
+
"DD_CLOUDWISE_API_PREFIX" => {version: ["A"]},
|
|
40
42
|
"DD_CRASHTRACKING_ENABLED" => {version: ["A"]},
|
|
41
43
|
"DD_DATA_STREAMS_ENABLED" => {version: ["A"]},
|
|
42
44
|
"DD_DBM_PROPAGATION_MODE" => {version: ["A"]},
|
|
@@ -48,6 +50,7 @@ module Datadog
|
|
|
48
50
|
"DD_ENV" => {version: ["A"]},
|
|
49
51
|
"DD_ERROR_TRACKING_HANDLED_ERRORS" => {version: ["A"]},
|
|
50
52
|
"DD_ERROR_TRACKING_HANDLED_ERRORS_INCLUDE" => {version: ["A"]},
|
|
53
|
+
"DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED" => {version: ["A"]},
|
|
51
54
|
"DD_GIT_COMMIT_SHA" => {version: ["A"]},
|
|
52
55
|
"DD_GIT_REPOSITORY_URL" => {version: ["A"]},
|
|
53
56
|
"DD_HEALTH_METRICS_ENABLED" => {version: ["A"]},
|
|
@@ -314,6 +317,7 @@ module Datadog
|
|
|
314
317
|
"DD_TRACE_TRILOGY_ENABLED" => {version: ["A"]},
|
|
315
318
|
"DD_TRACE_TRILOGY_PEER_SERVICE" => {version: ["A"]},
|
|
316
319
|
"DD_TRACE_TRILOGY_SERVICE_NAME" => {version: ["A"]},
|
|
320
|
+
"DD_TRACE_WATERDROP_ENABLED" => {version: ["A"]},
|
|
317
321
|
"DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH" => {version: ["A"]},
|
|
318
322
|
"DD_VERSION" => {version: ["A"]},
|
|
319
323
|
"OTEL_TRACES_SAMPLER_ARG" => {version: ["A"]}}.freeze
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative '../../utils/base64'
|
|
4
4
|
require_relative '../../../appsec/remote'
|
|
5
5
|
require_relative '../../../tracing/remote'
|
|
6
|
+
require_relative '../../../open_feature/remote'
|
|
6
7
|
|
|
7
8
|
module Datadog
|
|
8
9
|
module Core
|
|
@@ -38,6 +39,12 @@ module Datadog
|
|
|
38
39
|
register_receivers(Datadog::DI::Remote.receivers(@telemetry))
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
if settings.respond_to?(:open_feature) && settings.open_feature.enabled
|
|
43
|
+
register_capabilities(Datadog::OpenFeature::Remote.capabilities)
|
|
44
|
+
register_products(Datadog::OpenFeature::Remote.products)
|
|
45
|
+
register_receivers(Datadog::OpenFeature::Remote.receivers(@telemetry))
|
|
46
|
+
end
|
|
47
|
+
|
|
41
48
|
register_capabilities(Datadog::Tracing::Remote.capabilities)
|
|
42
49
|
register_products(Datadog::Tracing::Remote.products)
|
|
43
50
|
register_receivers(Datadog::Tracing::Remote.receivers(@telemetry))
|
|
@@ -68,12 +68,12 @@ module Datadog
|
|
|
68
68
|
|
|
69
69
|
# Starts the Remote Configuration worker without waiting for first run
|
|
70
70
|
def start
|
|
71
|
-
@worker.start
|
|
71
|
+
# @worker.start
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
# Is the Remote Configuration worker running?
|
|
75
75
|
def started?
|
|
76
|
-
@worker.started?
|
|
76
|
+
# @worker.started?
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# If the worker is not initialized, initialize it.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative '../../../core/transport/request'
|
|
4
4
|
require_relative '../../../core/transport/parcel'
|
|
5
|
+
require_relative 'http/config'
|
|
5
6
|
|
|
6
7
|
module Datadog
|
|
7
8
|
module Core
|
|
@@ -21,15 +22,6 @@ module Datadog
|
|
|
21
22
|
class Request < Datadog::Core::Transport::Request
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
# Config response
|
|
25
|
-
module Response
|
|
26
|
-
attr_reader :roots, :targets, :target_files, :client_configs
|
|
27
|
-
|
|
28
|
-
def empty?
|
|
29
|
-
@empty
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
25
|
# Config transport
|
|
34
26
|
class Transport
|
|
35
27
|
attr_reader :client, :apis, :default_api, :current_api_id, :logger
|
|
@@ -38,7 +30,7 @@ module Datadog
|
|
|
38
30
|
@apis = apis
|
|
39
31
|
@logger = logger
|
|
40
32
|
|
|
41
|
-
@client = HTTP::Client.new(current_api, logger: logger)
|
|
33
|
+
@client = Remote::Transport::HTTP::Config::Client.new(current_api, logger: logger)
|
|
42
34
|
end
|
|
43
35
|
|
|
44
36
|
##### there is only one transport! it's negotiation!
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
4
|
|
|
5
|
-
require_relative '
|
|
6
|
-
require_relative 'client'
|
|
5
|
+
require_relative '../../../transport/http/client'
|
|
7
6
|
require_relative '../../../utils/base64'
|
|
8
7
|
require_relative '../../../utils/truncation'
|
|
9
8
|
require_relative '../../../transport/http/response'
|
|
@@ -19,7 +18,6 @@ module Datadog
|
|
|
19
18
|
# Response from HTTP transport for remote configuration
|
|
20
19
|
class Response
|
|
21
20
|
include Datadog::Core::Transport::HTTP::Response
|
|
22
|
-
include Core::Remote::Transport::Config::Response
|
|
23
21
|
|
|
24
22
|
def initialize(http_response, options = {}) # standard:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
25
23
|
super(http_response)
|
|
@@ -114,6 +112,12 @@ module Datadog
|
|
|
114
112
|
end.freeze
|
|
115
113
|
end
|
|
116
114
|
|
|
115
|
+
attr_reader :roots, :targets, :target_files, :client_configs
|
|
116
|
+
|
|
117
|
+
def empty?
|
|
118
|
+
@empty
|
|
119
|
+
end
|
|
120
|
+
|
|
117
121
|
def inspect
|
|
118
122
|
"#{super}, #{
|
|
119
123
|
{
|
|
@@ -174,8 +178,8 @@ module Datadog
|
|
|
174
178
|
end
|
|
175
179
|
end
|
|
176
180
|
|
|
177
|
-
#
|
|
178
|
-
|
|
181
|
+
# Remote transport HTTP client
|
|
182
|
+
class Client < Core::Transport::HTTP::Client
|
|
179
183
|
def send_config_payload(request)
|
|
180
184
|
send_request(request) do |api, env|
|
|
181
185
|
api.send_config(env)
|
|
@@ -240,10 +244,6 @@ module Datadog
|
|
|
240
244
|
end
|
|
241
245
|
end
|
|
242
246
|
end
|
|
243
|
-
|
|
244
|
-
# Add remote configuration behavior to transport components
|
|
245
|
-
###### overrides send_payload! which calls send_<endpoint>! kills any other possible endpoint!
|
|
246
|
-
HTTP::Client.include(Config::Client)
|
|
247
247
|
end
|
|
248
248
|
end
|
|
249
249
|
end
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
4
|
|
|
5
|
-
require_relative '
|
|
6
|
-
require_relative 'client'
|
|
5
|
+
require_relative '../../../transport/http/client'
|
|
7
6
|
require_relative '../../../transport/http/response'
|
|
8
7
|
require_relative '../../../transport/http/api/endpoint'
|
|
9
8
|
|
|
@@ -17,7 +16,6 @@ module Datadog
|
|
|
17
16
|
# Response from HTTP transport for agent feature negotiation
|
|
18
17
|
class Response
|
|
19
18
|
include Datadog::Core::Transport::HTTP::Response
|
|
20
|
-
include Core::Remote::Transport::Negotiation::Response
|
|
21
19
|
|
|
22
20
|
def initialize(http_response, options = {})
|
|
23
21
|
super(http_response)
|
|
@@ -29,10 +27,24 @@ module Datadog
|
|
|
29
27
|
@config = options[:config]
|
|
30
28
|
@span_events = options[:span_events]
|
|
31
29
|
end
|
|
30
|
+
|
|
31
|
+
# @!attribute [r] version
|
|
32
|
+
# The version of the agent.
|
|
33
|
+
# @return [String]
|
|
34
|
+
# @!attribute [r] endpoints
|
|
35
|
+
# The HTTP endpoints the agent supports.
|
|
36
|
+
# @return [Array<String>]
|
|
37
|
+
# @!attribute [r] config
|
|
38
|
+
# The agent configuration. These are configured by the user when starting the agent, as well as any defaults.
|
|
39
|
+
# @return [Hash]
|
|
40
|
+
# @!attribute [r] span_events
|
|
41
|
+
# Whether the agent supports the top-level span events field in flushed spans.
|
|
42
|
+
# @return [Boolean,nil]
|
|
43
|
+
attr_reader :version, :endpoints, :config, :span_events
|
|
32
44
|
end
|
|
33
45
|
|
|
34
|
-
#
|
|
35
|
-
|
|
46
|
+
# Remote negotiation HTTP client
|
|
47
|
+
class Client < Core::Transport::HTTP::Client
|
|
36
48
|
def send_info_payload(request)
|
|
37
49
|
send_request(request) do |api, env|
|
|
38
50
|
api.send_info(env)
|
|
@@ -92,9 +104,6 @@ module Datadog
|
|
|
92
104
|
end
|
|
93
105
|
end
|
|
94
106
|
end
|
|
95
|
-
|
|
96
|
-
# Add negotiation behavior to transport components
|
|
97
|
-
HTTP::Client.include(Negotiation::Client)
|
|
98
107
|
end
|
|
99
108
|
end
|
|
100
109
|
end
|
|
@@ -4,6 +4,8 @@ require_relative '../../environment/container'
|
|
|
4
4
|
require_relative '../../environment/ext'
|
|
5
5
|
require_relative '../../transport/ext'
|
|
6
6
|
require_relative '../../transport/http'
|
|
7
|
+
require_relative 'config'
|
|
8
|
+
require_relative 'negotiation'
|
|
7
9
|
|
|
8
10
|
# TODO: Improve negotiation to allow per endpoint selection
|
|
9
11
|
#
|