cw-datadog 2.23.0.5 → 2.23.0.6

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 (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/datadog/core/cloudwise/client.rb +47 -37
  3. data/lib/datadog/core/cloudwise/component.rb +40 -39
  4. data/lib/datadog/core/cloudwise/docc_heartbeat_worker.rb +0 -1
  5. data/lib/datadog/core/cloudwise/docc_operation_worker.rb +5 -10
  6. data/lib/datadog/core/cloudwise/docc_registration_worker.rb +0 -1
  7. data/lib/datadog/core/cloudwise/probe_state.rb +9 -11
  8. data/lib/datadog/core/cloudwise/time_sync_worker.rb +2 -6
  9. data/lib/datadog/core/configuration/components.rb +1 -3
  10. data/lib/datadog/core/configuration/settings.rb +25 -31
  11. data/lib/datadog/core/environment/agent_info.rb +18 -0
  12. data/lib/datadog/core/remote/negotiation.rb +14 -0
  13. data/lib/datadog/core/transport/http/adapters/net.rb +8 -6
  14. data/lib/datadog/tracing/contrib/cloudwise/propagation.rb +80 -162
  15. data/lib/datadog/tracing/contrib/grape/endpoint.rb +2 -6
  16. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +0 -26
  17. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +0 -26
  18. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +26 -114
  19. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +21 -50
  20. data/lib/datadog/tracing/contrib/rack/middlewares.rb +82 -83
  21. data/lib/datadog/tracing/tracer.rb +10 -33
  22. data/lib/datadog/tracing/transport/http/api.rb +2 -4
  23. data/lib/datadog/tracing/transport/http/traces.rb +2 -2
  24. data/lib/datadog/tracing/transport/trace_formatter.rb +25 -22
  25. data/lib/datadog/tracing.rb +3 -3
  26. data/lib/datadog/version.rb +2 -2
  27. metadata +4 -4
@@ -1,132 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../cloudwise/propagation'
4
-
5
3
  module Datadog
6
4
  module Tracing
7
5
  module Contrib
8
6
  module Kafka
9
7
  module Instrumentation
10
8
  # Instrumentation for Kafka::Consumer
11
- # 这个模块直接 prepend 到 ::Kafka::Consumer,实例方法直接定义在模块中
12
9
  module Consumer
13
- # Thread-local 变量用于存储当前消息的 CLOUDWISE headers
14
- # 由于 ruby-kafka 的 process_message 事件在 block 调用时触发(instrument 包裹 block.call)
15
- # 执行顺序是:on_start -> block.call -> on_finish
16
- # 所以我们在 block 中存储 headers,在 on_finish 中提取
17
- CLOUDWISE_HEADERS_KEY = :datadog_kafka_cloudwise_headers
18
-
19
- class << self
20
- # 存储当前消息的 CLOUDWISE headers 到 Thread-local
21
- def store_cloudwise_headers(headers)
22
- Thread.current[CLOUDWISE_HEADERS_KEY] = headers
23
- end
24
-
25
- # 获取 Thread-local 中存储的 CLOUDWISE headers(不清除)
26
- # 用于 on_finish 中获取 headers
27
- def peek_cloudwise_headers
28
- Thread.current[CLOUDWISE_HEADERS_KEY]
29
- end
30
-
31
- # 获取并清除 Thread-local 中存储的 CLOUDWISE headers
32
- def fetch_cloudwise_headers
33
- headers = Thread.current[CLOUDWISE_HEADERS_KEY]
34
- Thread.current[CLOUDWISE_HEADERS_KEY] = nil
35
- headers
36
- end
37
-
38
- # 清除 Thread-local 中存储的 CLOUDWISE headers
39
- def clear_cloudwise_headers
40
- Thread.current[CLOUDWISE_HEADERS_KEY] = nil
41
- end
42
- end
43
-
44
- # 实例方法直接定义在模块中,会被 prepend 到 ::Kafka::Consumer
45
- def each_message(**kwargs, &block)
46
- return super unless block
47
-
48
- original_block = block
49
- wrapped_block = proc do |message|
50
- headers = message.headers || {}
51
-
52
- # 处理 DSM checkpoint
53
- if Datadog::DataStreams.enabled?
54
- Datadog.logger.debug { "Kafka each_message: DSM enabled for topic #{message.topic}" }
55
-
56
- begin
57
- Datadog::DataStreams.set_consume_checkpoint(
58
- type: 'kafka',
59
- source: message.topic,
60
- auto_instrumentation: true
61
- ) { |key| headers[key] }
62
- rescue => e
63
- Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
64
- end
65
- end
66
-
67
- # 存储 CLOUDWISE headers 到 Thread-local
68
- # 这会在 process_message 事件的 on_start 之后、on_finish 之前执行
69
- # 所以 on_finish 可以获取到正确的 headers
70
- Datadog::Tracing::Contrib::Kafka::Instrumentation::Consumer.store_cloudwise_headers(headers)
71
-
72
- # 调用原始 block
73
- original_block.call(message)
10
+ def each_message(**kwargs, &block)
11
+ if Datadog::DataStreams.enabled?
12
+ super do |message|
13
+ headers = message.headers || {}
14
+
15
+ Datadog::DataStreams.set_consume_checkpoint(
16
+ type: 'kafka',
17
+ source: message.topic,
18
+ auto_instrumentation: true
19
+ ) { |key| headers[key] }
20
+
21
+ block.call(message)
74
22
  end
75
-
76
- super(**kwargs, &wrapped_block)
23
+ else
24
+ super
77
25
  end
26
+ end
78
27
 
79
- def each_batch(**kwargs, &block)
80
- return super unless block
81
-
82
- original_block = block
83
- wrapped_block = proc do |batch|
84
- # 处理 DSM checkpoint
85
- if Datadog::DataStreams.enabled?
86
- Datadog.logger.debug { "Kafka each_batch: DSM enabled for topic #{batch.topic}" }
87
-
88
- begin
89
- Datadog::DataStreams.set_consume_checkpoint(
90
- type: 'kafka',
91
- source: batch.topic,
92
- auto_instrumentation: true
93
- )
94
- rescue => e
95
- Datadog.logger.debug("Error setting DSM checkpoint: #{e.class}: #{e}")
96
- end
97
- end
98
-
99
- # 从批量消息的第一条消息中提取 headers 并存储到 Thread-local
100
- store_batch_cloudwise_headers!(batch)
28
+ def each_batch(**kwargs, &block)
29
+ if Datadog::DataStreams.enabled?
30
+ super do |batch|
31
+ Datadog::DataStreams.set_consume_checkpoint(
32
+ type: 'kafka',
33
+ source: batch.topic,
34
+ auto_instrumentation: true
35
+ )
101
36
 
102
- # 调用原始 block
103
- original_block.call(batch)
37
+ block.call(batch)
104
38
  end
105
-
106
- super(**kwargs, &wrapped_block)
39
+ else
40
+ super
107
41
  end
108
-
109
- private
110
-
111
- # 从批量消息的第一条消息中提取 headers 并存储到 Thread-local
112
- # @param batch [Object] 批量消息对象
113
- def store_batch_cloudwise_headers!(batch)
114
- return unless batch
115
-
116
- # 获取批量消息中的消息列表
117
- messages = batch.respond_to?(:messages) ? batch.messages : nil
118
- return unless messages && !messages.empty?
119
-
120
- # 从第一条消息中提取 headers
121
- first_message = messages.first
122
- return unless first_message
123
-
124
- headers = first_message.respond_to?(:headers) ? first_message.headers : nil
125
- return unless headers
126
-
127
- Datadog::Tracing::Contrib::Kafka::Instrumentation::Consumer.store_cloudwise_headers(headers)
128
- rescue => e
129
- Datadog.logger.debug("Error storing CLOUDWISE headers from batch: #{e.class}: #{e}")
130
42
  end
131
43
  end
132
44
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../cloudwise/propagation'
4
-
5
3
  module Datadog
6
4
  module Tracing
7
5
  module Contrib
@@ -15,71 +13,44 @@ module Datadog
15
13
 
16
14
  module InstanceMethods
17
15
  def deliver_messages(**kwargs)
18
- begin
19
- pending_messages = instance_variable_get(:@pending_message_queue)
16
+ if Datadog::DataStreams.enabled?
17
+ pending_messages = instance_variable_get(:@pending_message_queue)
20
18
 
21
- if pending_messages && !pending_messages.empty?
22
- pending_messages.each do |message|
23
- message.headers ||= {}
19
+ if pending_messages && !pending_messages.empty?
20
+ pending_messages.each do |message|
21
+ message.headers ||= {}
24
22
 
25
- # 注入 DSM checkpoint
26
- if Datadog::DataStreams.enabled?
27
- Datadog::DataStreams.set_produce_checkpoint(
28
- type: 'kafka',
29
- destination: message.topic,
30
- auto_instrumentation: true
31
- ) do |key, value|
32
- message.headers[key] = value
33
- end
23
+ Datadog::DataStreams.set_produce_checkpoint(
24
+ type: 'kafka',
25
+ destination: message.topic,
26
+ auto_instrumentation: true
27
+ ) do |key, value|
28
+ message.headers[key] = value
34
29
  end
35
-
36
- # 注入 CLOUDWISE header
37
- inject_cloudwise_headers!(message.headers, message.topic)
38
30
  end
39
31
  end
40
- rescue => e
41
- Datadog.logger.debug("Error in Kafka producer instrumentation: #{e.class}: #{e}")
42
32
  end
43
33
 
44
34
  super
45
35
  end
46
36
 
47
37
  def send_messages(messages, **kwargs)
48
- begin
49
- messages.each do |message|
50
- message[:headers] ||= {}
51
-
52
- # 注入 DSM checkpoint
53
- if Datadog::DataStreams.enabled?
54
- Datadog::DataStreams.set_produce_checkpoint(
55
- type: 'kafka',
56
- destination: message[:topic],
57
- auto_instrumentation: true
58
- ) do |key, value|
59
- message[:headers][key] = value
60
- end
38
+ if Datadog::DataStreams.enabled?
39
+ messages.each do |message|
40
+ message[:headers] ||= {}
41
+
42
+ Datadog::DataStreams.set_produce_checkpoint(
43
+ type: 'kafka',
44
+ destination: message[:topic],
45
+ auto_instrumentation: true
46
+ ) do |key, value|
47
+ message[:headers][key] = value
61
48
  end
62
-
63
- # 注入 CLOUDWISE header
64
- inject_cloudwise_headers!(message[:headers], message[:topic])
65
49
  end
66
- rescue => e
67
- Datadog.logger.debug("Error in Kafka producer instrumentation: #{e.class}: #{e}")
68
50
  end
69
51
 
70
52
  super
71
53
  end
72
-
73
- private
74
-
75
- # 注入 CLOUDWISE headers 到 Kafka 消息
76
- # @param headers [Hash] 消息 headers
77
- # @param topic [String] Kafka topic 名称
78
- def inject_cloudwise_headers!(headers, topic)
79
- Cloudwise::Propagation.inject_kafka_headers!(headers, topic)
80
- rescue => e
81
- Datadog.logger.debug("Error injecting CLOUDWISE headers: #{e.class}: #{e}")
82
- end
83
54
  end
84
55
  end
85
56
  end
@@ -29,7 +29,9 @@ module Datadog
29
29
  # information available at the Rack level.
30
30
  class TraceMiddleware
31
31
  # ✅ 优化:缓存 ENV 配置为常量,避免每次请求读取操作系统环境变量
32
+ # rubocop:disable CustomCops/EnvUsageCop
32
33
  CLOUDWISE_JS_ENABLED = ENV.fetch('CLOUDWISE_JS_CONFIG', 'false') == 'true'
34
+ # rubocop:enable CustomCops/EnvUsageCop
33
35
 
34
36
  def initialize(app)
35
37
  @app = app
@@ -50,113 +52,109 @@ module Datadog
50
52
  Tracing.continue_trace!(trace_digest) if trace_digest
51
53
  end
52
54
 
53
- # 需要在创建 span 之前提取信息
54
- request_headers = Header::RequestHeaderCollection.new(env)
55
+ # 需要在创建 span 之前提取信息
56
+ request_headers = Header::RequestHeaderCollection.new(env)
55
57
 
56
- # 处理 CLOUDWISEREQUESTINFO(前端调用)
57
- cloudwise_info = request_headers.get('CLOUDWISEREQUESTINFO')
58
- request_id = nil
58
+ # 处理 CLOUDWISEREQUESTINFO(前端调用)
59
+ cloudwise_info = request_headers.get('CLOUDWISEREQUESTINFO')
60
+ request_id = nil
59
61
 
60
- if cloudwise_info
61
- # 提取 request_id
62
- request_id = extract_request_id(cloudwise_info)
62
+ if cloudwise_info
63
+ # 提取 request_id
64
+ request_id = extract_request_id(cloudwise_info)
63
65
 
64
- if request_id
65
- Datadog.logger.debug do
66
- "Extracted request_id from CLOUDWISEREQUESTINFO: #{request_id}"
66
+ if request_id
67
+ Datadog.logger.debug do
68
+ "Extracted request_id from CLOUDWISEREQUESTINFO: #{request_id}"
69
+ end
67
70
  end
68
71
  end
69
- end
70
72
 
71
- # 处理 CLOUDWISE(外部服务调用,如 Java/PHP)
72
- cloudwise_header = request_headers.get('CLOUDWISE')
73
+ # 处理 CLOUDWISE(外部服务调用,如 Java/PHP)
74
+ cloudwise_header = request_headers.get('CLOUDWISE')
73
75
 
74
- TraceProxyMiddleware.call(env, configuration) do
75
- trace_options = {type: Tracing::Metadata::Ext::HTTP::TYPE_INBOUND}
76
- trace_options[:service] = configuration[:service_name] if configuration[:service_name]
76
+ TraceProxyMiddleware.call(env, configuration) do
77
+ trace_options = {type: Tracing::Metadata::Ext::HTTP::TYPE_INBOUND}
78
+ trace_options[:service] = configuration[:service_name] if configuration[:service_name]
77
79
 
78
- # start a new request span and attach it to the current Rack environment;
79
- # we must ensure that the span `resource` is set later
80
- request_span = Tracing.trace(Ext::SPAN_REQUEST, **trace_options)
81
- request_span.resource = nil
80
+ # start a new request span and attach it to the current Rack environment;
81
+ # we must ensure that the span `resource` is set later
82
+ request_span = Tracing.trace(Ext::SPAN_REQUEST, **trace_options)
83
+ request_span.resource = nil
82
84
 
83
- # 如果存在 request_id,将其作为 span 的 cwsa_trace 字段
84
- if request_id
85
- request_span.set_tag('cwsa_trace', request_id)
86
- Datadog.logger.debug do
87
- "Set cwsa_trace tag on span: #{request_id}"
85
+ # 如果存在 request_id,将其作为 span 的 cwsa_trace 字段
86
+ if request_id
87
+ request_span.set_tag('cwsa_trace', request_id)
88
+ Datadog.logger.debug do
89
+ "Set cwsa_trace tag on span: #{request_id}"
90
+ end
88
91
  end
89
- end
90
92
 
91
- # 如果存在 CLOUDWISE 头(外部服务调用),提取并设置字段到 span
92
- if cloudwise_header
93
- require_relative '../cloudwise/propagation'
94
- Cloudwise::Propagation.extract_and_tag_from_header!(request_span, cloudwise_header)
95
- end
93
+ # 如果存在 CLOUDWISE 头(外部服务调用),提取并设置字段到 span
94
+ if cloudwise_header
95
+ require_relative '../cloudwise/propagation'
96
+ Cloudwise::Propagation.extract_and_tag_from_header!(request_span, cloudwise_header)
97
+ end
96
98
 
97
- # 提取 CLOUDWISE-OTHER 头并添加到根 span
98
- require_relative '../cloudwise/propagation'
99
- Cloudwise::Propagation.extract_other_from_request!(request_span, request_headers)
99
+ # 提取 CLOUDWISE-OTHER 头并添加到根 span
100
+ require_relative '../cloudwise/propagation'
101
+ Cloudwise::Propagation.extract_other_from_request!(request_span, request_headers)
100
102
 
101
- # When tracing and distributed tracing are both disabled, `.active_trace` will be `nil`,
102
- # Return a null object to continue operation
103
- request_trace = Tracing.active_trace || TraceOperation.new
104
- env[Ext::RACK_ENV_REQUEST_SPAN] = request_span
103
+ # When tracing and distributed tracing are both disabled, `.active_trace` will be `nil`,
104
+ # Return a null object to continue operation
105
+ request_trace = Tracing.active_trace || TraceOperation.new
106
+ env[Ext::RACK_ENV_REQUEST_SPAN] = request_span
105
107
 
106
- Datadog::Core::Remote::Tie::Tracing.tag(boot, request_span)
108
+ Datadog::Core::Remote::Tie::Tracing.tag(boot, request_span)
107
109
 
108
- # Copy the original env, before the rest of the stack executes.
109
- # Values may change; we want values before that happens.
110
- original_env = env.dup
110
+ # Copy the original env, before the rest of the stack executes.
111
+ # Values may change; we want values before that happens.
112
+ original_env = env.dup
111
113
 
112
- # call the rest of the stack
113
- status, headers, response = @app.call(env)
114
+ # call the rest of the stack
115
+ status, headers, response = @app.call(env)
114
116
 
115
- # 如果存在 cloudwise_info,在响应头中添加 CLOUDWISETRACE
116
- if cloudwise_info
117
- headers ||= {}
118
- headers['CLOUDWISETRACE'] = 'true'
119
- Datadog.logger.debug do
120
- "Added CLOUDWISETRACE response header"
117
+ # 如果存在 cloudwise_info,在响应头中添加 CLOUDWISETRACE
118
+ if cloudwise_info
119
+ headers ||= {}
120
+ headers['CLOUDWISETRACE'] = 'true'
121
+ Datadog.logger.debug do
122
+ "Added CLOUDWISETRACE response header"
123
+ end
121
124
  end
122
- end
123
125
 
124
- # 如果启用了 CLOUDWISE_JS_CONFIG,在响应头中添加 CLOUDWISE(用于 RUM 追踪)
125
- # 默认关闭,可通过环境变量 CLOUDWISE_JS_CONFIG=true 开启
126
- # 使用常量替代每次 ENV 读取
127
- if CLOUDWISE_JS_ENABLED
128
- headers ||= {}
129
- require_relative '../cloudwise/propagation'
126
+ # 如果启用了 CLOUDWISE_JS_CONFIG,在响应头中添加 CLOUDWISE(用于 RUM 追踪)
127
+ # 默认关闭,可通过环境变量 CLOUDWISE_JS_CONFIG=true 开启
128
+ # 使用常量替代每次 ENV 读取
129
+ if CLOUDWISE_JS_ENABLED
130
+ headers ||= {}
131
+ require_relative '../cloudwise/propagation'
132
+
133
+ # 构建 CLOUDWISE 响应头值
134
+ # Only add CLOUDWISE header if Cloudwise is active (not suspended)
135
+ service_name = Datadog.configuration.service
136
+ if service_name && request_span
137
+ cloudwise_value = Cloudwise::Propagation.build_cloudwise_value(
138
+ span: request_span,
139
+ trace: request_trace,
140
+ service_name: service_name,
141
+ target_url: nil # 响应头不需要 target_url
142
+ )
130
143
 
131
- # 构建 CLOUDWISE 响应头值
132
- # Only add CLOUDWISE header if Cloudwise is active (not suspended)
133
- service_name = Datadog.configuration.service
134
- if service_name && request_span
135
- cloudwise_value = Cloudwise::Propagation.build_cloudwise_value(
136
- span: request_span,
137
- trace: request_trace,
138
- service_name: service_name,
139
- target_url: nil # 响应头不需要 target_url
140
- )
141
-
142
- headers['CLOUDWISE'] = cloudwise_value
143
- Datadog.logger.debug do
144
- "Added CLOUDWISE response header for RUM: #{cloudwise_value}"
145
- end
146
- elsif service_name && request_span
147
- Datadog.logger.debug do
148
- "Skipped CLOUDWISE response header: Cloudwise probe suspended"
144
+ headers['CLOUDWISE'] = cloudwise_value
145
+ Datadog.logger.debug do
146
+ "Added CLOUDWISE response header for RUM: #{cloudwise_value}"
147
+ end
149
148
  end
150
149
  end
151
- end
152
150
 
153
- [status, headers, response]
151
+ [status, headers, response]
154
152
 
155
- # Here we really want to catch *any* exception, not only StandardError,
156
- # as we really have no clue of what is in the block,
157
- # and it is user code which should be executed no matter what.
158
- # It's not a problem since we re-raise it afterwards so for example a
159
- # SignalException::Interrupt would still bubble up.
153
+ # Here we really want to catch *any* exception, not only StandardError,
154
+ # as we really have no clue of what is in the block,
155
+ # and it is user code which should be executed no matter what.
156
+ # It's not a problem since we re-raise it afterwards so for example a
157
+ # SignalException::Interrupt would still bubble up.
160
158
  rescue Exception => e # rubocop:disable Lint/RescueException
161
159
  # catch exceptions that may be raised in the middleware chain
162
160
  # Note: if a middleware catches an Exception without re raising,
@@ -205,6 +203,7 @@ module Datadog
205
203
  end
206
204
  nil
207
205
  end
206
+
208
207
  # rubocop:disable Metrics/AbcSize
209
208
  # rubocop:disable Metrics/CyclomaticComplexity
210
209
  # rubocop:disable Metrics/PerceivedComplexity
@@ -145,7 +145,7 @@ module Datadog
145
145
  &block
146
146
  )
147
147
  return skip_trace(name, &block) unless enabled
148
-
148
+
149
149
  # Check Cloudwise probe state - if suspended, don't create spans
150
150
  return skip_trace(name, &block) if cloudwise_probe_suspended?
151
151
 
@@ -599,43 +599,20 @@ module Datadog
599
599
 
600
600
  # Check if Cloudwise probe is suspended
601
601
  # If suspended, we should not create any spans
602
+ # rubocop:disable Metrics/MethodLength
602
603
  def cloudwise_probe_suspended?
603
- # First try to use the components reference passed to tracer
604
- components = @components
605
-
606
- # If no components reference, try global Datadog.components
607
- if components.nil? && defined?(Datadog.components)
608
- components = Datadog.components
609
- end
610
-
611
- unless components
612
- logger.debug { "Cloudwise check: No components available" }
613
- return false
614
- end
615
-
616
- unless components.respond_to?(:cloudwise)
617
- logger.debug { "Cloudwise check: Components doesn't respond to cloudwise" }
618
- return false
619
- end
620
-
604
+ components = @components || (defined?(Datadog.components) && Datadog.components)
605
+ return false unless components&.respond_to?(:cloudwise)
606
+
621
607
  cloudwise = components.cloudwise
622
- unless cloudwise&.enabled?
623
- logger.debug { "Cloudwise check: Cloudwise not enabled or is nil" }
624
- return false
625
- end
626
-
627
- suspended = cloudwise.probe_state.suspended?
628
- logger.debug { "Cloudwise check: suspended? = #{suspended}" }
629
-
630
- suspended
608
+ return false unless cloudwise&.enabled?
609
+
610
+ cloudwise.probe_state.suspended?
631
611
  rescue => e
632
- # If any error occurs, don't block span creation
633
- # Log error only once to avoid log spam
634
- CLOUDWISE_CHECK_LOG_ONLY_ONCE.run do
635
- logger.debug { "Cloudwise probe check error: #{e.message}" }
636
- end
612
+ CLOUDWISE_CHECK_LOG_ONLY_ONCE.run { logger.debug { "Cloudwise probe check error: #{e.message}" } }
637
613
  false
638
614
  end
615
+ # rubocop:enable Metrics/MethodLength
639
616
 
640
617
  CLOUDWISE_CHECK_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
641
618
  private_constant :CLOUDWISE_CHECK_LOG_ONLY_ONCE
@@ -47,7 +47,7 @@ module Datadog
47
47
  base_path = '/api/v2/traces'
48
48
 
49
49
  return base_path unless defined?(Datadog.configuration) &&
50
- Datadog.configuration.respond_to?(:cloudwise)
50
+ Datadog.configuration.respond_to?(:cloudwise)
51
51
 
52
52
  # 优先级 1: api_prefix_mode 模式配置(最高优先级,简化配置)
53
53
  if Datadog.configuration.cloudwise.respond_to?(:api_prefix_mode)
@@ -94,15 +94,13 @@ module Datadog
94
94
  end
95
95
  end
96
96
  nil
97
- else
98
- nil
99
97
  end
100
98
  end
101
99
 
102
100
  # 检查是否启用 integrated_mode
103
101
  def cloudwise_integrated_mode?
104
102
  return false unless defined?(Datadog.configuration) &&
105
- Datadog.configuration.respond_to?(:cloudwise)
103
+ Datadog.configuration.respond_to?(:cloudwise)
106
104
 
107
105
  integrated_mode = Datadog.configuration.cloudwise.integrated_mode
108
106
  token = Datadog.configuration.cloudwise.token
@@ -100,7 +100,7 @@ module Datadog
100
100
  # Add routing key header
101
101
  env.headers['routingKey'] = 'rubyTopic'
102
102
 
103
- env.headers['AccountId'] = ENV['CLOUDWISE_ACCOUNT_ID'] || '110'
103
+ env.headers['AccountId'] = DATADOG_ENV['CLOUDWISE_ACCOUNT_ID'] || '110'
104
104
 
105
105
  # Encode body & type
106
106
  env.headers[HEADER_CONTENT_TYPE] = encoder.content_type
@@ -142,7 +142,7 @@ module Datadog
142
142
  def build_mock_response(env)
143
143
  # Create a mock HTTP response
144
144
  mock_http_response = Struct.new(:code, :payload).new(200, '{}')
145
- response_options = { trace_count: env.request.parcel.trace_count }
145
+ response_options = {trace_count: env.request.parcel.trace_count}
146
146
  Traces::Response.new(mock_http_response, response_options)
147
147
  end
148
148
  end
@@ -207,47 +207,50 @@ module Datadog
207
207
  end
208
208
 
209
209
  def tag_cloudwise_metadata!
210
+ # ✅ 优化:使用 set_tags 批量设置,减少锁竞争
211
+ tags = {}
212
+
210
213
  # Get all Cloudwise metadata from environment variables (set by Cloudwise client during registration)
211
- account_id = ENV['CLOUDWISE_ACCOUNT_ID']
212
- host_id = ENV['CLOUDWISE_HOST_ID']
213
- agent_id = ENV['CLOUDWISE_AGENT_ID']
214
- host_name = ENV['CLOUDWISE_HOST_NAME']
215
- instance_id = ENV['CLOUDWISE_INSTANCE_ID']
216
-
217
- # Set all metadata tags on root span
218
- root_span.set_tag('account_id', account_id) if account_id && !account_id.empty?
219
- root_span.set_tag('host_id', host_id) if host_id && !host_id.empty?
220
- root_span.set_tag('agent_id', agent_id) if agent_id && !agent_id.empty?
221
- root_span.set_tag('host_name', host_name) if host_name && !host_name.empty?
222
- root_span.set_tag('instance_id', instance_id) if instance_id && !instance_id.empty?
214
+ account_id = DATADOG_ENV['CLOUDWISE_ACCOUNT_ID']
215
+ host_id = DATADOG_ENV['CLOUDWISE_HOST_ID']
216
+ agent_id = DATADOG_ENV['CLOUDWISE_AGENT_ID']
217
+ host_name = DATADOG_ENV['CLOUDWISE_HOST_NAME']
218
+ instance_id = DATADOG_ENV['CLOUDWISE_INSTANCE_ID']
219
+
220
+ # Collect all metadata tags
221
+ tags['account_id'] = account_id if account_id && !account_id.empty?
222
+ tags['host_id'] = host_id if host_id && !host_id.empty?
223
+ tags['agent_id'] = agent_id if agent_id && !agent_id.empty?
224
+ tags['host_name'] = host_name if host_name && !host_name.empty?
225
+ tags['instance_id'] = instance_id if instance_id && !instance_id.empty?
223
226
 
224
227
  # Add host_ip (server IP address)
225
228
  require_relative '../contrib/cloudwise/propagation'
226
229
  host_ip = Contrib::Cloudwise::Propagation.get_host_ip
227
- root_span.set_tag('host_ip', host_ip) if host_ip && !host_ip.empty?
230
+ tags['host_ip'] = host_ip if host_ip && !host_ip.empty?
228
231
 
229
232
  # Generate and set app_id based on service name
230
233
  service_name = Datadog.configuration.service
231
234
  if service_name && !service_name.empty?
232
235
  app_id = Contrib::Cloudwise::Propagation.generate_app_id(service_name)
233
- root_span.set_tag('app_id', app_id) if app_id
236
+ tags['app_id'] = app_id if app_id
234
237
  end
235
238
 
236
239
  # Add new Cloudwise fields: service_instance_id, service_type_from, parent_sys, sys
237
240
  # Generate service_instance_id based on IP + process path + PID
238
241
  service_instance_id = Contrib::Cloudwise::Propagation.generate_service_instance_id
239
- root_span.set_tag('service_instance_id', service_instance_id) if service_instance_id
242
+ tags['service_instance_id'] = service_instance_id if service_instance_id
240
243
 
241
244
  # Get sys from environment variable (default: 'default')
242
245
  sys = Contrib::Cloudwise::Propagation.get_sys
243
- root_span.set_tag('sys', sys) if sys
246
+ tags['sys'] = sys if sys
244
247
 
245
- unless root_span.get_tag('service_type_from')
246
- root_span.set_tag('service_type_from', '')
247
- end
248
- unless root_span.get_tag('parent_sys')
249
- root_span.set_tag('parent_sys', '')
250
- end
248
+ # 如果 service_type_from 和 parent_sys 不存在,设置为空字符串
249
+ tags['service_type_from'] = '' unless root_span.get_tag('service_type_from')
250
+ tags['parent_sys'] = '' unless root_span.get_tag('parent_sys')
251
+
252
+ # 批量设置所有 tags
253
+ root_span.set_tags(tags) unless tags.empty?
251
254
  end
252
255
 
253
256
  def tag_git_repository_url!