cw-datadog 2.23.0.4 → 2.23.0.5

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libdatadog_api/feature_flags.c +554 -0
  3. data/ext/libdatadog_api/feature_flags.h +5 -0
  4. data/ext/libdatadog_api/init.c +2 -0
  5. data/lib/datadog/core/cloudwise/client.rb +99 -4
  6. data/lib/datadog/core/cloudwise/component.rb +55 -13
  7. data/lib/datadog/core/cloudwise/docc_operation_worker.rb +11 -1
  8. data/lib/datadog/core/cloudwise/license_worker.rb +7 -0
  9. data/lib/datadog/core/cloudwise/time_sync_worker.rb +200 -0
  10. data/lib/datadog/core/configuration/settings.rb +12 -0
  11. data/lib/datadog/core/configuration/supported_configurations.rb +14 -0
  12. data/lib/datadog/core/environment/ext.rb +6 -0
  13. data/lib/datadog/core/environment/process.rb +79 -0
  14. data/lib/datadog/core/feature_flags.rb +61 -0
  15. data/lib/datadog/core/tag_normalizer.rb +84 -0
  16. data/lib/datadog/core/transport/http/adapters/net.rb +8 -0
  17. data/lib/datadog/core/utils/array.rb +29 -0
  18. data/lib/datadog/core/utils.rb +2 -0
  19. data/lib/datadog/data_streams/processor.rb +1 -1
  20. data/lib/datadog/di/transport/http.rb +6 -2
  21. data/lib/datadog/di/transport/input.rb +62 -2
  22. data/lib/datadog/open_feature/evaluation_engine.rb +19 -9
  23. data/lib/datadog/open_feature/ext.rb +1 -0
  24. data/lib/datadog/open_feature/native_evaluator.rb +38 -0
  25. data/lib/datadog/open_feature/noop_evaluator.rb +3 -3
  26. data/lib/datadog/open_feature/provider.rb +15 -8
  27. data/lib/datadog/open_feature/remote.rb +1 -1
  28. data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
  29. data/lib/datadog/opentelemetry/metrics.rb +110 -0
  30. data/lib/datadog/opentelemetry/sdk/configurator.rb +25 -1
  31. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +38 -0
  32. data/lib/datadog/opentelemetry.rb +3 -0
  33. data/lib/datadog/tracing/configuration/ext.rb +1 -0
  34. data/lib/datadog/tracing/contrib/cloudwise/propagation.rb +143 -17
  35. data/lib/datadog/tracing/contrib/grape/endpoint.rb +141 -0
  36. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +26 -0
  37. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +26 -0
  38. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +79 -9
  39. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +29 -6
  40. data/lib/datadog/tracing/contrib/rack/middlewares.rb +6 -54
  41. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  42. data/lib/datadog/tracing/transport/serializable_trace.rb +8 -1
  43. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  44. data/lib/datadog/tracing/transport/traces.rb +3 -5
  45. data/lib/datadog/version.rb +1 -1
  46. metadata +29 -4
@@ -157,7 +157,7 @@ module Datadog
157
157
  imagePath: get_agent_path,
158
158
  ip: host_ip,
159
159
  agentId: generate_agent_id(host_ip),
160
- timestamp: Time.now.to_i,
160
+ timestamp: get_adjusted_timestamp_seconds,
161
161
  routingKey: 'HeartBeat',
162
162
  classPath: '',
163
163
  isFirst: @is_first_heartbeat ? 1 : 0,
@@ -279,7 +279,7 @@ module Datadog
279
279
  sample: calculate_sample_rate,
280
280
  physical_ip: detect_container? ? get_host_real_ip : '',
281
281
  container_id: detect_container? ? get_container_id : '',
282
- sys: ENV['CW_SYS'] || 'default',
282
+ sys: get_cloudwise_sys,
283
283
  env_tag: Datadog.configuration.env || 'default'
284
284
  }
285
285
  }
@@ -325,8 +325,61 @@ module Datadog
325
325
  post_docc("/api/ext/gaia/daemon/report/#{@agent_instance_id}", data)
326
326
  end
327
327
 
328
- private
328
+ # 获取服务器时间戳接口
329
+ # @return [Hash] { success: true/false, server_timestamp: Integer (毫秒), offset_ms: Integer }
330
+ def fetch_server_timestamp
331
+ path = apply_api_prefix('/api/v70/timestamp')
332
+ uri = URI.join(base_url, path)
333
+
334
+ Cloudwise.log_debug { "Cloudwise: Fetching server timestamp from #{uri}" }
335
+
336
+ http = Net::HTTP.new(uri.host, uri.port)
337
+ http.use_ssl = (uri.scheme == 'https')
338
+ http.open_timeout = 5
339
+ http.read_timeout = 5
340
+
341
+ request = Net::HTTP::Get.new(uri.path)
342
+ request['User-Agent'] = "Datadog-Ruby-Agent/#{Datadog::VERSION::STRING}"
343
+ request['DD-Internal-Untraced-Request'] = '1'
344
+
345
+ # 记录请求前的本地时间
346
+ local_before = (Time.now.to_f * 1000).to_i
347
+
348
+ response = http.request(request)
349
+
350
+ # 记录请求后的本地时间
351
+ local_after = (Time.now.to_f * 1000).to_i
352
+
353
+ if response.code.to_i == 200
354
+ server_timestamp = response.body.to_s.strip.to_i
355
+
356
+ # 使用请求前后的中间时间作为本地参考时间
357
+ local_timestamp = (local_before + local_after) / 2
358
+
359
+ # 计算时间偏移(服务器时间 - 本地时间)
360
+ # 正值表示服务器时间比本地快,负值表示服务器时间比本地慢
361
+ offset_ms = server_timestamp - local_timestamp
362
+
363
+ Cloudwise.log_debug do
364
+ "Cloudwise: Server timestamp sync - server=#{server_timestamp}, local=#{local_timestamp}, offset=#{offset_ms}ms"
365
+ end
366
+
367
+ {
368
+ success: true,
369
+ server_timestamp: server_timestamp,
370
+ local_timestamp: local_timestamp,
371
+ offset_ms: offset_ms
372
+ }
373
+ else
374
+ Cloudwise.log_warn { "Cloudwise: path: #{path} Failed to fetch server timestamp: #{response.code}" }
375
+ { success: false, error: "HTTP #{response.code}" }
376
+ end
377
+ rescue => e
378
+ Cloudwise.log_error { "Cloudwise: Error fetching server timestamp: #{e.message}" }
379
+ { success: false, error: e.message }
380
+ end
329
381
 
382
+ private
330
383
  def post(path, data)
331
384
  # 统一处理 API 路径前缀
332
385
  path = apply_api_prefix(path)
@@ -380,6 +433,31 @@ module Datadog
380
433
  end
381
434
 
382
435
 
436
+ # 获取校正后的秒级时间戳
437
+ # 如果启用了时间同步,会应用偏移量校正
438
+ # @return [Integer] 校正后的秒级时间戳
439
+ def get_adjusted_timestamp_seconds
440
+ local_time_s = Time.now.to_i
441
+ if defined?(TimeSyncWorker) && TimeSyncWorker.sync_enabled?
442
+ # offset_ms 是毫秒,转换为秒
443
+ local_time_s + (TimeSyncWorker.offset_ms / 1000)
444
+ else
445
+ local_time_s
446
+ end
447
+ end
448
+
449
+ # 获取校正后的毫秒级时间戳
450
+ # 如果启用了时间同步,会应用偏移量校正
451
+ # @return [Integer] 校正后的毫秒级时间戳
452
+ def get_adjusted_timestamp_ms
453
+ local_time_ms = (Time.now.to_f * 1000).to_i
454
+ if defined?(TimeSyncWorker) && TimeSyncWorker.sync_enabled?
455
+ local_time_ms + TimeSyncWorker.offset_ms
456
+ else
457
+ local_time_ms
458
+ end
459
+ end
460
+
383
461
  # 获取本机 IP 地址
384
462
  # 优先获取外网 IP(通过创建 UDP 连接,不实际发送数据)
385
463
  # 如果失败,尝试获取局域网 IP
@@ -623,7 +701,8 @@ module Datadog
623
701
  '/api/v1/agent/heartbeat',
624
702
  '/api/v1/agent/fuseHeart',
625
703
  '/v2/app/create',
626
- '/v2/licence/verification'
704
+ '/v2/licence/verification',
705
+ '/api/v70/timestamp'
627
706
  ]
628
707
 
629
708
  # 检查是否是需要添加前缀的路径
@@ -704,6 +783,22 @@ module Datadog
704
783
  end
705
784
 
706
785
 
786
+ # 获取 Cloudwise sys 配置值
787
+ # 优先级: Datadog.configuration.cloudwise.sys > CW_SYS 环境变量 > 默认值 'default'
788
+ # @return [String] sys 值
789
+ def get_cloudwise_sys
790
+ # 优先从配置读取
791
+ if defined?(Datadog.configuration) &&
792
+ Datadog.configuration.respond_to?(:cloudwise) &&
793
+ Datadog.configuration.cloudwise.respond_to?(:sys)
794
+ sys = Datadog.configuration.cloudwise.sys
795
+ return sys if sys && !sys.empty? && sys != 'default'
796
+ end
797
+
798
+ # 其次从环境变量读取
799
+ ENV['CW_SYS'] || 'default'
800
+ end
801
+
707
802
  # Get current run user
708
803
  def get_run_user
709
804
  ENV['USER'] || ENV['USERNAME'] || 'cloudwise'
@@ -9,6 +9,7 @@ require_relative 'app_registration_worker'
9
9
  require_relative 'docc_registration_worker'
10
10
  require_relative 'docc_heartbeat_worker'
11
11
  require_relative 'docc_operation_worker'
12
+ require_relative 'time_sync_worker'
12
13
 
13
14
  module Datadog
14
15
  module Core
@@ -46,7 +47,8 @@ module Datadog
46
47
  class Component
47
48
  attr_reader :client, :probe_state, :host_id_worker, :heartbeat_worker,
48
49
  :license_worker, :app_registration_worker, :logger,
49
- :docc_registration_worker, :docc_heartbeat_worker, :docc_operation_worker
50
+ :docc_registration_worker, :docc_heartbeat_worker, :docc_operation_worker,
51
+ :time_sync_worker
50
52
 
51
53
  # 类级别的单例锁,确保全局只初始化一次
52
54
  @initialization_mutex = Mutex.new
@@ -185,6 +187,9 @@ module Datadog
185
187
  def stop
186
188
  return unless @enabled
187
189
 
190
+ # 停止时间同步 worker(两种模式都需要)
191
+ @time_sync_worker&.stop(true)
192
+
188
193
  if @client.use_integrated_mode?
189
194
  @docc_heartbeat_worker&.stop(true)
190
195
  @docc_registration_worker&.stop(true)
@@ -216,6 +221,13 @@ module Datadog
216
221
  return { enabled: false } unless @enabled
217
222
 
218
223
  probe_status = probe_state.status
224
+ # 获取时间同步状态
225
+ time_sync_status = if defined?(Datadog::Core::Cloudwise::TimeSyncWorker)
226
+ Datadog::Core::Cloudwise::TimeSyncWorker.status
227
+ else
228
+ { enabled: false }
229
+ end
230
+
219
231
  base_status = {
220
232
  enabled: true,
221
233
  integrated_mode: @client.use_integrated_mode?,
@@ -223,7 +235,10 @@ module Datadog
223
235
  probe_active: probe_state.active?,
224
236
  probe_suspended: probe_state.suspended?,
225
237
  license_valid: probe_status[:license_valid],
226
- license_running: license_worker&.running?
238
+ license_running: license_worker&.running?,
239
+ time_sync_enabled: time_sync_status[:enabled],
240
+ time_sync_offset_ms: time_sync_status[:offset_ms],
241
+ time_sync_running: time_sync_worker&.running?
227
242
  }
228
243
 
229
244
  if @client.use_integrated_mode?
@@ -282,6 +297,13 @@ module Datadog
282
297
  probe_state: probe_state,
283
298
  interval: settings.cloudwise.license_check_interval
284
299
  )
300
+
301
+ # 5. Time Sync Worker (3 min interval, depends on License)
302
+ @time_sync_worker = TimeSyncWorker.new(
303
+ client: client,
304
+ logger: logger,
305
+ probe_state: probe_state
306
+ )
285
307
  end
286
308
 
287
309
  # 初始化 DOCC 模式的 workers
@@ -315,6 +337,13 @@ module Datadog
315
337
  probe_state: probe_state,
316
338
  interval: settings.cloudwise.license_check_interval
317
339
  )
340
+
341
+ # 5. Time Sync Worker (3 min interval, depends on License)
342
+ @time_sync_worker = TimeSyncWorker.new(
343
+ client: client,
344
+ logger: logger,
345
+ probe_state: probe_state
346
+ )
318
347
  end
319
348
 
320
349
  # 检查实例是否已经启动
@@ -335,7 +364,8 @@ module Datadog
335
364
  # 3. Start Heartbeat worker
336
365
  # 4. Start App Registration worker (non-blocking)
337
366
  # 5. Start License worker
338
- # 6. ProbeState controls whether data collection is active
367
+ # 6. Start Time Sync worker (3 min interval)
368
+ # 7. ProbeState controls whether data collection is active
339
369
  def start_cloudwise_workers_when_ready
340
370
  Thread.new do
341
371
  Thread.current.name = 'Cloudwise-Initializer'
@@ -368,7 +398,6 @@ module Datadog
368
398
  # ============================================================
369
399
  # STEP 4: Start License worker
370
400
  # ============================================================
371
- #
372
401
  @license_worker.start
373
402
 
374
403
  # Wait for first successful license validation
@@ -376,6 +405,12 @@ module Datadog
376
405
  sleep(1)
377
406
  end
378
407
 
408
+ # ============================================================
409
+ # STEP 5: Start Time Sync worker (3 min interval)
410
+ # ============================================================
411
+ Cloudwise.log_debug { 'Cloudwise: Starting Time Sync worker (3 min interval)...' }
412
+ @time_sync_worker.start
413
+
379
414
  # ============================================================
380
415
  # All validations passed - Probe is now ACTIVE
381
416
  # ============================================================
@@ -392,7 +427,8 @@ module Datadog
392
427
  # 2. 等待第一次心跳成功
393
428
  # 3. 启动 DOCC 注册 worker
394
429
  # 4. 启动 License worker
395
- # 5. 启动 DOCC 操作 worker
430
+ # 5. 启动 Time Sync worker (3 min interval)
431
+ # 6. 启动 DOCC 操作 worker
396
432
  def start_docc_workers_when_ready
397
433
  Thread.new do
398
434
  Thread.current.name = 'Cloudwise-DOCC-Initializer'
@@ -400,11 +436,11 @@ module Datadog
400
436
  # ============================================================
401
437
  # STEP 1: Start DOCC Heartbeat worker
402
438
  # ============================================================
403
- Cloudwise.log_debug { 'Cloudwise DOCC: Starting heartbeat worker...' }
439
+ Cloudwise.log_debug { 'Cloudwise docc: Starting heartbeat worker...' }
404
440
  @docc_heartbeat_worker.start
405
441
 
406
442
  # Wait for first successful heartbeat
407
- Cloudwise.log_debug { 'Cloudwise DOCC: Waiting for first successful heartbeat...' }
443
+ Cloudwise.log_debug { 'Cloudwise docc: Waiting for first successful heartbeat...' }
408
444
  until probe_state.docc_heartbeat_active?
409
445
  sleep(1)
410
446
  end
@@ -412,13 +448,13 @@ module Datadog
412
448
  # ============================================================
413
449
  # STEP 2: Start DOCC Registration worker
414
450
  # ============================================================
415
- Cloudwise.log_debug { 'Cloudwise DOCC: Starting registration worker...' }
451
+ Cloudwise.log_debug { 'Cloudwise docc: Starting registration worker...' }
416
452
  @docc_registration_worker.start
417
453
 
418
454
  # ============================================================
419
455
  # STEP 3: Start License worker
420
456
  # ============================================================
421
- Cloudwise.log_debug { 'Cloudwise DOCC: Starting license worker...' }
457
+ Cloudwise.log_debug { 'Cloudwise docc: Starting license worker...' }
422
458
  @license_worker.start
423
459
 
424
460
  # Wait for first successful license validation
@@ -427,17 +463,23 @@ module Datadog
427
463
  end
428
464
 
429
465
  # ============================================================
430
- # STEP 4: Start DOCC Operation worker
466
+ # STEP 4: Start Time Sync worker (3 min interval)
467
+ # ============================================================
468
+ Cloudwise.log_debug { 'Cloudwise docc: Starting Time Sync worker (3 min interval)...' }
469
+ @time_sync_worker.start
470
+
471
+ # ============================================================
472
+ # STEP 5: Start DOCC Operation worker
431
473
  # ============================================================
432
- Cloudwise.log_debug { 'Cloudwise DOCC: Starting operation worker...' }
474
+ Cloudwise.log_debug { 'Cloudwise docc: Starting operation worker...' }
433
475
  @docc_operation_worker.start
434
476
 
435
477
  # ============================================================
436
478
  # All validations passed - Probe is now ACTIVE
437
479
  # ============================================================
438
- Cloudwise.log_debug { 'Cloudwise DOCC: Data collection and reporting now enabled.' }
480
+ Cloudwise.log_debug { 'Cloudwise docc: Data collection and reporting now enabled.' }
439
481
  rescue => e
440
- Cloudwise.log_error { "Cloudwise DOCC: Error in background initializer: #{e.class.name} #{e.message}" }
482
+ Cloudwise.log_error { "Cloudwise docc: Error in background initializer: #{e.class.name} #{e.message}" }
441
483
  Cloudwise.log_error { e.backtrace.join("\n") }
442
484
  end
443
485
  end
@@ -170,10 +170,20 @@ module Datadog
170
170
  agent_id: 'rubyagent'
171
171
  },
172
172
  status: status,
173
- timestamp: Time.now.to_i * 1000
173
+ timestamp: get_adjusted_timestamp_ms
174
174
  }
175
175
  end
176
176
 
177
+ # 获取校正后的毫秒时间戳
178
+ def get_adjusted_timestamp_ms
179
+ local_time_ms = (Time.now.to_f * 1000).to_i
180
+ if defined?(TimeSyncWorker) && TimeSyncWorker.sync_enabled?
181
+ local_time_ms + TimeSyncWorker.offset_ms
182
+ else
183
+ local_time_ms
184
+ end
185
+ end
186
+
177
187
  # 批量上报操作结果
178
188
  def report_operation_results(results)
179
189
  result = client.docc_report_operation(results)
@@ -159,9 +159,16 @@ module Datadog
159
159
  end
160
160
 
161
161
  # 仅在状态发生变化时上报熔断状态
162
+ # 注意:融合模式(use_integrated_mode)下不进行上报
162
163
  # @param fuse_state [Integer] 熔断状态: 0-正常, 1-熔断
163
164
  # @param fuse_describe [Integer, nil] 熔断描述: 7/8/9/10,正常状态时为nil
164
165
  def report_fuse_state_if_changed(fuse_state, fuse_describe)
166
+ # 融合模式下不上报熔断状态
167
+ if client.use_integrated_mode?
168
+ Cloudwise.log_debug { 'Cloudwise: Integrated mode enabled, skip fuse state reporting' }
169
+ return
170
+ end
171
+
165
172
  # 检查状态是否发生变化
166
173
  if @last_fuse_state == fuse_state && @last_fuse_describe == fuse_describe
167
174
  Cloudwise.log_debug { "Cloudwise: Fuse state unchanged (state: #{fuse_state}, describe: #{fuse_describe}), skip reporting" }
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../worker'
4
+ require_relative '../workers/async'
5
+ require_relative '../workers/polling'
6
+
7
+ module Datadog
8
+ module Core
9
+ module Cloudwise
10
+ # Worker that synchronizes time with server every 3 minutes
11
+ # 时间同步 Worker,每 3 分钟执行一次
12
+ # 整合了时间偏移量管理和定时同步功能
13
+ class TimeSyncWorker < Worker
14
+ include Workers::Polling
15
+
16
+ # 3 minutes interval (180 seconds)
17
+ DEFAULT_INTERVAL = 180
18
+
19
+ # 最大偏移量阈值(毫秒)- 超过此值才进行校正
20
+ # 小于 100ms 的偏移可以忽略
21
+ OFFSET_THRESHOLD_MS = 100
22
+
23
+ # 类级别的时间偏移量状态(全局共享)
24
+ @offset_ms = 0
25
+ @sync_enabled = false
26
+ @last_sync_time = nil
27
+ @state_mutex = Mutex.new
28
+
29
+ class << self
30
+ attr_reader :state_mutex
31
+
32
+ # 获取当前时间偏移量(毫秒)
33
+ # @return [Integer] 时间偏移量,正值表示服务器时间比本地快
34
+ def offset_ms
35
+ @offset_ms ||= 0
36
+ end
37
+
38
+ # 设置时间偏移量
39
+ # @param value [Integer] 偏移量(毫秒)
40
+ def offset_ms=(value)
41
+ @offset_ms = value.to_i
42
+ end
43
+
44
+ # 获取时间偏移量(纳秒)
45
+ # @return [Integer] 时间偏移量(纳秒)
46
+ def offset_ns
47
+ offset_ms * 1_000_000
48
+ end
49
+
50
+ # 检查是否启用时间同步
51
+ # @return [Boolean]
52
+ def sync_enabled?
53
+ @sync_enabled ||= false
54
+ end
55
+
56
+ # 启用时间同步
57
+ def enable_sync!
58
+ @sync_enabled = true
59
+ end
60
+
61
+ # 禁用时间同步
62
+ def disable_sync!
63
+ @sync_enabled = false
64
+ @offset_ms = 0
65
+ end
66
+
67
+ # 上次同步时间
68
+ # @return [Integer, nil] 毫秒时间戳
69
+ def last_sync_time
70
+ @last_sync_time
71
+ end
72
+
73
+ # 设置上次同步时间
74
+ def last_sync_time=(value)
75
+ @last_sync_time = value
76
+ end
77
+
78
+ # 校正时间戳(纳秒)
79
+ # 将本地时间戳转换为服务器时间戳
80
+ # @param local_time_ns [Integer] 本地时间戳(纳秒)
81
+ # @return [Integer] 校正后的时间戳(纳秒)
82
+ def adjust_timestamp_ns(local_time_ns)
83
+ return local_time_ns unless sync_enabled?
84
+ return local_time_ns if offset_ms.abs < OFFSET_THRESHOLD_MS
85
+
86
+ local_time_ns + offset_ns
87
+ end
88
+
89
+ # 校正 Time 对象
90
+ # @param time [Time] 本地时间
91
+ # @return [Time] 校正后的时间
92
+ def adjust_time(time)
93
+ return time unless sync_enabled?
94
+ return time if offset_ms.abs < OFFSET_THRESHOLD_MS
95
+
96
+ time + (offset_ms / 1000.0)
97
+ end
98
+
99
+ # 重置状态(用于测试)
100
+ def reset!
101
+ @offset_ms = 0
102
+ @sync_enabled = false
103
+ @last_sync_time = nil
104
+ end
105
+
106
+ # 获取同步状态信息
107
+ # @return [Hash]
108
+ def status
109
+ {
110
+ enabled: sync_enabled?,
111
+ offset_ms: offset_ms,
112
+ offset_ns: offset_ns,
113
+ last_sync_time: last_sync_time
114
+ }
115
+ end
116
+ end
117
+
118
+ attr_reader :client
119
+
120
+ def initialize(client:, logger:, probe_state:, **options)
121
+ @client = client
122
+ @logger = logger
123
+ @probe_state = probe_state
124
+
125
+ # Workers::Async::Thread settings
126
+ self.fork_policy = options.fetch(:fork_policy, Workers::Async::Thread::FORK_POLICY_STOP)
127
+
128
+ # Workers::IntervalLoop settings
129
+ self.loop_base_interval = options.fetch(:interval, DEFAULT_INTERVAL)
130
+
131
+ self.enabled = options.fetch(:enabled, true)
132
+ end
133
+
134
+ def perform
135
+ # 只有在 License 校验通过后才执行时间同步
136
+ unless probe_state.license_valid?
137
+ Cloudwise.log_debug { 'Cloudwise: Waiting for license validation before time sync' }
138
+ return true
139
+ end
140
+
141
+ Cloudwise.log_debug { 'Cloudwise: Performing server time synchronization' }
142
+
143
+ if sync_time!
144
+ Cloudwise.log_debug { "Cloudwise: Time sync completed, offset=#{self.class.offset_ms}ms" }
145
+ else
146
+ Cloudwise.log_warn { 'Cloudwise: Time sync failed' }
147
+ end
148
+
149
+ true
150
+ rescue => e
151
+ Cloudwise.log_error { "Cloudwise: Time sync worker error: #{e.class.name} #{e.message}" }
152
+ true # Continue running
153
+ end
154
+
155
+ # Public method to start the worker
156
+ def start
157
+ return false if !enabled? || started?
158
+
159
+ # Start the async worker thread
160
+ perform
161
+ end
162
+
163
+ private
164
+
165
+ attr_reader :logger, :probe_state
166
+
167
+ # 执行时间同步
168
+ # @return [Boolean] 是否同步成功
169
+ def sync_time!
170
+ return false unless client
171
+
172
+ result = client.fetch_server_timestamp
173
+ if result[:success]
174
+ self.class.state_mutex.synchronize do
175
+ self.class.offset_ms = result[:offset_ms]
176
+ self.class.last_sync_time = (Time.now.to_f * 1000).to_i
177
+ self.class.enable_sync!
178
+ end
179
+
180
+ Cloudwise.log_info do
181
+ "Cloudwise TimeSync: Synchronized with server, offset=#{self.class.offset_ms}ms"
182
+ end
183
+
184
+ true
185
+ else
186
+ Cloudwise.log_warn do
187
+ "Cloudwise TimeSync: Failed to sync - #{result[:error]}"
188
+ end
189
+ false
190
+ end
191
+ rescue => e
192
+ Cloudwise.log_error do
193
+ "Cloudwise TimeSync: Error during sync - #{e.message}"
194
+ end
195
+ false
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -12,6 +12,7 @@ require_relative '../remote/ext'
12
12
  require_relative '../../profiling/ext'
13
13
 
14
14
  require_relative '../../tracing/configuration/settings'
15
+ require_relative '../../opentelemetry/configuration/settings'
15
16
 
16
17
  module Datadog
17
18
  module Core
@@ -1095,6 +1096,15 @@ module Datadog
1095
1096
  o.default 180
1096
1097
  end
1097
1098
  end
1099
+ # Enable experimental process tags propagation such that payloads like spans contain the process tag.
1100
+ #
1101
+ # @default `DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED` environment variable, otherwise `false`
1102
+ # @return [Boolean]
1103
+ option :experimental_propagate_process_tags_enabled do |o|
1104
+ o.env 'DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED'
1105
+ o.default false
1106
+ o.type :bool
1107
+ end
1098
1108
 
1099
1109
  # Tracer specific configuration starting with APM (e.g. DD_APM_TRACING_ENABLED).
1100
1110
  # @public_api
@@ -1123,6 +1133,8 @@ module Datadog
1123
1133
  # TODO: Tracing should manage its own settings.
1124
1134
  # Keep this extension here for now to keep things working.
1125
1135
  extend Datadog::Tracing::Configuration::Settings
1136
+
1137
+ extend Datadog::OpenTelemetry::Configuration::Settings
1126
1138
  end
1127
1139
  # standard:enable Metrics/BlockLength
1128
1140
  end
@@ -51,6 +51,7 @@ module Datadog
51
51
  "DD_ERROR_TRACKING_HANDLED_ERRORS" => {version: ["A"]},
52
52
  "DD_ERROR_TRACKING_HANDLED_ERRORS_INCLUDE" => {version: ["A"]},
53
53
  "DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED" => {version: ["A"]},
54
+ "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED" => {version: ["A"]},
54
55
  "DD_GIT_COMMIT_SHA" => {version: ["A"]},
55
56
  "DD_GIT_REPOSITORY_URL" => {version: ["A"]},
56
57
  "DD_HEALTH_METRICS_ENABLED" => {version: ["A"]},
@@ -63,6 +64,7 @@ module Datadog
63
64
  "DD_INTEGRATION_SERVICE" => {version: ["A"]},
64
65
  "DD_LOGS_INJECTION" => {version: ["A"]},
65
66
  "DD_METRIC_AGENT_PORT" => {version: ["A"]},
67
+ "DD_METRICS_OTEL_ENABLED" => {version: ["A"]},
66
68
  "DD_PROFILING_ALLOCATION_ENABLED" => {version: ["A"]},
67
69
  "DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED" => {version: ["A"]},
68
70
  "DD_PROFILING_ENABLED" => {version: ["A"]},
@@ -320,6 +322,18 @@ module Datadog
320
322
  "DD_TRACE_WATERDROP_ENABLED" => {version: ["A"]},
321
323
  "DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH" => {version: ["A"]},
322
324
  "DD_VERSION" => {version: ["A"]},
325
+ "OTEL_EXPORTER_OTLP_ENDPOINT" => {version: ["A"]},
326
+ "OTEL_EXPORTER_OTLP_HEADERS" => {version: ["A"]},
327
+ "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT" => {version: ["A"]},
328
+ "OTEL_EXPORTER_OTLP_METRICS_HEADERS" => {version: ["A"]},
329
+ "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL" => {version: ["A"]},
330
+ "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE" => {version: ["A"]},
331
+ "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT" => {version: ["A"]},
332
+ "OTEL_EXPORTER_OTLP_PROTOCOL" => {version: ["A"]},
333
+ "OTEL_EXPORTER_OTLP_TIMEOUT" => {version: ["A"]},
334
+ "OTEL_METRIC_EXPORT_INTERVAL" => {version: ["A"]},
335
+ "OTEL_METRIC_EXPORT_TIMEOUT" => {version: ["A"]},
336
+ "OTEL_METRICS_EXPORTER" => {version: ["A"]},
323
337
  "OTEL_TRACES_SAMPLER_ARG" => {version: ["A"]}}.freeze
324
338
 
325
339
  ALIASES =
@@ -33,8 +33,14 @@ module Datadog
33
33
  LANG_INTERPRETER = "#{RUBY_ENGINE}-#{RUBY_PLATFORM}"
34
34
  LANG_PLATFORM = RUBY_PLATFORM
35
35
  LANG_VERSION = RUBY_VERSION
36
+ PROCESS_TYPE = 'script' # Out of the options [jar, script, class, executable], we consider Ruby to always be a script
36
37
  RUBY_ENGINE = ::RUBY_ENGINE # e.g. 'ruby', 'jruby', 'truffleruby'
37
38
  TAG_ENV = 'env'
39
+ TAG_ENTRYPOINT_BASEDIR = "entrypoint.basedir"
40
+ TAG_ENTRYPOINT_NAME = "entrypoint.name"
41
+ TAG_ENTRYPOINT_WORKDIR = "entrypoint.workdir"
42
+ TAG_ENTRYPOINT_TYPE = "entrypoint.type"
43
+ TAG_PROCESS_TAGS = "_dd.tags.process"
38
44
  TAG_SERVICE = 'service'
39
45
  TAG_VERSION = 'version'
40
46