datadog 2.33.0 → 2.35.0

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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -1
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +20 -0
  4. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +2 -15
  5. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  6. data/ext/datadog_profiling_native_extension/stack_recorder.c +6 -11
  7. data/lib/datadog/ai_guard/configuration.rb +1 -0
  8. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +53 -39
  9. data/lib/datadog/ai_guard/evaluation.rb +6 -1
  10. data/lib/datadog/ai_guard/ext.rb +12 -1
  11. data/lib/datadog/appsec/api_security/route_extractor.rb +3 -0
  12. data/lib/datadog/appsec/component.rb +4 -1
  13. data/lib/datadog/appsec/compressed_json.rb +2 -2
  14. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +3 -3
  15. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  16. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +9 -40
  17. data/lib/datadog/appsec/default_header_tags.rb +48 -0
  18. data/lib/datadog/core/configuration/components.rb +8 -1
  19. data/lib/datadog/core/configuration/settings.rb +16 -7
  20. data/lib/datadog/core/configuration/supported_configurations.rb +10 -0
  21. data/lib/datadog/core/environment/ext.rb +4 -0
  22. data/lib/datadog/core/environment/identity.rb +15 -1
  23. data/lib/datadog/core/environment/process.rb +50 -27
  24. data/lib/datadog/core/remote/client/capabilities.rb +11 -2
  25. data/lib/datadog/core/remote/transport/http/config.rb +5 -5
  26. data/lib/datadog/core/telemetry/request.rb +0 -2
  27. data/lib/datadog/core/transport/response.rb +1 -1
  28. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +3 -2
  29. data/lib/datadog/core/utils/{array.rb → enumerable_compat.rb} +2 -2
  30. data/lib/datadog/core/utils/hash.rb +0 -23
  31. data/lib/datadog/core/utils/spawn_monkey_patch.rb +46 -16
  32. data/lib/datadog/data_streams/pathway_context.rb +3 -3
  33. data/lib/datadog/di/code_tracker.rb +43 -22
  34. data/lib/datadog/di/contrib/active_record.rb +6 -2
  35. data/lib/datadog/di/instrumenter.rb +24 -4
  36. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  37. data/lib/datadog/di/remote.rb +4 -4
  38. data/lib/datadog/di/serializer.rb +5 -5
  39. data/lib/datadog/di/utils.rb +42 -14
  40. data/lib/datadog/opentelemetry/configuration/settings.rb +65 -0
  41. data/lib/datadog/opentelemetry/ext.rb +9 -0
  42. data/lib/datadog/opentelemetry/logs.rb +98 -0
  43. data/lib/datadog/opentelemetry/metrics.rb +10 -46
  44. data/lib/datadog/opentelemetry/sdk/configurator.rb +40 -0
  45. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +37 -0
  46. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  47. data/lib/datadog/opentelemetry.rb +1 -0
  48. data/lib/datadog/profiling/collectors/thread_context.rb +0 -4
  49. data/lib/datadog/profiling/component.rb +3 -11
  50. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -2
  51. data/lib/datadog/profiling/stack_recorder.rb +0 -4
  52. data/lib/datadog/symbol_database/component.rb +409 -0
  53. data/lib/datadog/symbol_database/configuration.rb +2 -2
  54. data/lib/datadog/symbol_database/extractor.rb +32 -4
  55. data/lib/datadog/symbol_database/remote.rb +175 -0
  56. data/lib/datadog/symbol_database/scope_batcher.rb +8 -0
  57. data/lib/datadog/symbol_database/service_version.rb +11 -2
  58. data/lib/datadog/symbol_database/symbol.rb +6 -3
  59. data/lib/datadog/symbol_database/uploader.rb +62 -8
  60. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  61. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  62. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  63. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  64. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  65. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +1 -0
  66. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +8 -0
  67. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  68. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +4 -1
  69. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +4 -1
  70. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +4 -1
  71. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +4 -1
  72. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +4 -1
  73. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +4 -1
  74. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +4 -1
  75. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -4
  76. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -4
  77. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
  78. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -5
  79. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
  80. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  81. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  82. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -5
  83. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +2 -2
  84. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +1 -5
  85. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
  86. data/lib/datadog/tracing/contrib/excon/middleware.rb +1 -5
  87. data/lib/datadog/tracing/contrib/ext.rb +3 -1
  88. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -5
  89. data/lib/datadog/tracing/contrib/grape/endpoint.rb +3 -0
  90. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +1 -0
  91. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +1 -5
  92. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -5
  93. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  94. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -0
  95. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -0
  96. data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -5
  97. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
  98. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
  99. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -0
  100. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +5 -5
  101. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -5
  102. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +1 -5
  103. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -5
  104. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +2 -2
  105. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +1 -5
  106. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -5
  107. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +3 -0
  108. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +2 -2
  109. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  110. data/lib/datadog/tracing/contrib/racecar/event.rb +1 -5
  111. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +23 -0
  112. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -0
  113. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +2 -0
  114. data/lib/datadog/tracing/contrib/rails/runner.rb +2 -0
  115. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +4 -2
  116. data/lib/datadog/tracing/contrib/redis/tags.rb +0 -5
  117. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +2 -0
  118. data/lib/datadog/tracing/contrib/resque/resque_job.rb +1 -0
  119. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +1 -5
  120. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  121. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +4 -1
  122. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -0
  123. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -0
  124. data/lib/datadog/tracing/contrib/sequel/utils.rb +0 -5
  125. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  126. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  127. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  128. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  129. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  130. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  131. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  132. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +3 -2
  133. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  134. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -0
  135. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  136. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  137. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +1 -5
  138. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +1 -1
  139. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -13
  140. data/lib/datadog/tracing/distributed/trace_context.rb +0 -28
  141. data/lib/datadog/tracing/metadata/ext.rb +10 -0
  142. data/lib/datadog/tracing/span_operation.rb +13 -0
  143. data/lib/datadog/tracing/trace_operation.rb +22 -0
  144. data/lib/datadog/tracing/tracer.rb +9 -0
  145. data/lib/datadog/tracing/transport/traces.rb +2 -2
  146. data/lib/datadog/version.rb +1 -1
  147. metadata +16 -10
@@ -91,6 +91,14 @@ module Datadog
91
91
  return
92
92
  end
93
93
 
94
+ # Marked uploaded before perform_upload runs. This is intentional:
95
+ # symdb extraction is a one-shot operation per process — extract_all
96
+ # walks ObjectSpace once and never revisits a module within the same
97
+ # process. The Set deduplicates within a single extraction run, not
98
+ # across upload attempts. Failed uploads are not retried; symbols
99
+ # from a failed batch are lost until the next process restart, by
100
+ # design (matches Python and Go; Java retries via OkHttp, .NET via
101
+ # exponential backoff — Ruby does neither).
94
102
  @uploaded_modules.add(scope.name)
95
103
  @file_count += 1
96
104
 
@@ -16,15 +16,18 @@ module Datadog
16
16
  #
17
17
  # @api private
18
18
  class ServiceVersion
19
- attr_reader :service, :env, :version, :language, :scopes
19
+ attr_reader :service, :env, :version, :language, :scopes, :upload_id, :batch_num, :final
20
20
 
21
21
  # Initialize a new ServiceVersion
22
22
  # @param service [String] Service name (required, from DD_SERVICE)
23
23
  # @param env [String, nil] Environment (from DD_ENV, passed through unchanged)
24
24
  # @param version [String, nil] Version (from DD_VERSION, passed through unchanged)
25
25
  # @param scopes [Array<Scope>] Top-level scopes (required)
26
+ # @param upload_id [String, nil] UUID identifying the logical upload (shared by all batches)
27
+ # @param batch_num [Integer, nil] 1-indexed batch number within the upload
28
+ # @param final [Boolean, nil] true if this is the last batch of the upload
26
29
  # @raise [ArgumentError] if service empty or scopes not an array
27
- def initialize(service:, env:, version:, scopes:)
30
+ def initialize(service:, env:, version:, scopes:, upload_id: nil, batch_num: nil, final: nil)
28
31
  raise ArgumentError, 'service is required' if service.nil? || service.empty?
29
32
  raise ArgumentError, 'scopes must be an array' unless scopes.is_a?(Array)
30
33
 
@@ -33,6 +36,9 @@ module Datadog
33
36
  @version = version
34
37
  @language = 'ruby'
35
38
  @scopes = scopes
39
+ @upload_id = upload_id
40
+ @batch_num = batch_num
41
+ @final = final
36
42
  end
37
43
 
38
44
  # Convert service version to Hash for JSON serialization.
@@ -44,6 +50,9 @@ module Datadog
44
50
  version: version,
45
51
  language: language,
46
52
  scopes: scopes.map(&:to_h),
53
+ upload_id: upload_id,
54
+ batch_num: batch_num,
55
+ final: final,
47
56
  }
48
57
  end
49
58
 
@@ -42,17 +42,20 @@ module Datadog
42
42
  end
43
43
 
44
44
  # Convert symbol to Hash for JSON serialization.
45
- # Removes nil values to reduce payload size.
45
+ # The `type` key is always present per the symdb JSON schema — emit nil
46
+ # when the type cannot be determined (the common case in Ruby since
47
+ # parameters and instance variables carry no declared type).
48
+ # `language_specifics` is omitted when nil to reduce payload size.
46
49
  # @return [Hash] Symbol as hash with symbol keys
47
50
  def to_h
51
+ # @type var h: Hash[::Symbol, untyped]
48
52
  h = {
49
53
  symbol_type: symbol_type,
50
54
  name: name,
51
55
  line: line,
52
56
  type: type,
53
- language_specifics: language_specifics,
54
57
  }
55
- h.compact!
58
+ h[:language_specifics] = language_specifics if language_specifics
56
59
  h
57
60
  end
58
61
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'securerandom'
4
5
  require 'zlib'
5
6
  require 'stringio'
6
7
  require_relative '../core/environment/identity'
@@ -45,6 +46,12 @@ module Datadog
45
46
  agent_settings: agent_settings,
46
47
  logger: @logger,
47
48
  )
49
+
50
+ # Protects the lazy initialization of @upload_pid/@upload_id and the
51
+ # @batch_num increment in next_upload_metadata. ScopeBatcher calls
52
+ # upload_scopes outside its own mutex, so two threads (e.g. a size-
53
+ # triggered flush and the timer/shutdown path) can race here.
54
+ @metadata_mutex = Mutex.new
48
55
  end
49
56
 
50
57
  # Upload a batch of scopes to the agent.
@@ -56,7 +63,8 @@ module Datadog
56
63
  def upload_scopes(scopes)
57
64
  return if scopes.empty?
58
65
 
59
- json_data = build_symbol_payload(scopes)
66
+ upload_id, batch_num = next_upload_metadata
67
+ json_data = build_symbol_payload(scopes, upload_id: upload_id, batch_num: batch_num)
60
68
  compressed_data = Zlib.gzip(json_data)
61
69
 
62
70
  # Emitted unconditionally so the rare oversized case is observable.
@@ -72,7 +80,7 @@ module Datadog
72
80
  return
73
81
  end
74
82
 
75
- perform_http_upload(compressed_data, scopes.size)
83
+ perform_http_upload(compressed_data, scopes.size, upload_id: upload_id, batch_num: batch_num)
76
84
  rescue => e
77
85
  @logger.debug { "symdb: upload failed: #{e.class}: #{e.message}" }
78
86
  @telemetry&.report(e, description: 'symdb: upload failed')
@@ -82,31 +90,44 @@ module Datadog
82
90
 
83
91
  # Build JSON payload from scopes.
84
92
  # @param scopes [Array<Scope>] Scopes to serialize
93
+ # @param upload_id [String] UUID identifying the logical upload
94
+ # @param batch_num [Integer] 1-indexed batch number within the upload
85
95
  # @return [String] JSON string
86
- def build_symbol_payload(scopes)
96
+ def build_symbol_payload(scopes, upload_id:, batch_num:)
87
97
  ServiceVersion.new(
88
98
  service: @settings.service,
89
99
  env: @settings.env,
90
100
  version: @settings.version,
91
101
  scopes: scopes,
102
+ upload_id: upload_id,
103
+ batch_num: batch_num,
104
+ # Always false: the Ruby tracer continuously uploads new code
105
+ # as files are loaded; there is no defined end-of-upload point.
106
+ final: false,
92
107
  ).to_json
93
108
  end
94
109
 
95
110
  # Perform HTTP POST with multipart form-data via transport layer.
96
111
  # @param compressed_data [String] GZIP compressed JSON payload
97
112
  # @param scope_count [Integer] Number of scopes (for logging)
113
+ # @param upload_id [String] UUID identifying the logical upload
114
+ # @param batch_num [Integer] 1-indexed batch number within the upload
98
115
  # @return [void]
99
- def perform_http_upload(compressed_data, scope_count)
100
- form = build_multipart_form(compressed_data)
116
+ def perform_http_upload(compressed_data, scope_count, upload_id:, batch_num:)
117
+ form = build_multipart_form(compressed_data, upload_id: upload_id, batch_num: batch_num)
101
118
  response = @transport.send_symbols(form)
102
119
  handle_response(response, scope_count)
103
120
  end
104
121
 
105
122
  # Build multipart form-data with event metadata and compressed symbols.
106
123
  # @param compressed_data [String] GZIP compressed JSON payload
124
+ # @param upload_id [String] UUID identifying the logical upload
125
+ # @param batch_num [Integer] 1-indexed batch number within the upload
107
126
  # @return [Hash] Form data hash with UploadIO objects
108
- def build_multipart_form(compressed_data)
109
- event_io = StringIO.new(build_event_metadata)
127
+ def build_multipart_form(compressed_data, upload_id:, batch_num:)
128
+ event_io = StringIO.new(
129
+ build_event_metadata(compressed_data.bytesize, upload_id: upload_id, batch_num: batch_num),
130
+ )
110
131
  file_io = StringIO.new(compressed_data)
111
132
 
112
133
  event_upload = Datadog::Core::Vendor::Multipart::Post::UploadIO.new(
@@ -128,17 +149,50 @@ module Datadog
128
149
  end
129
150
 
130
151
  # Build event.json metadata part.
152
+ # @param attachment_size [Integer] Size of the compressed attachment in bytes
153
+ # @param upload_id [String] UUID identifying the logical upload
154
+ # @param batch_num [Integer] 1-indexed batch number within the upload
131
155
  # @return [String] JSON string for event metadata
132
- def build_event_metadata
156
+ def build_event_metadata(attachment_size, upload_id:, batch_num:)
133
157
  JSON.generate(
134
158
  ddsource: 'ruby',
135
159
  service: @settings.service,
160
+ version: @settings.version,
161
+ language: 'ruby',
136
162
  runtimeId: Datadog::Core::Environment::Identity.id,
137
163
  parentId: nil, # Fork tracking deferred for MVP
138
164
  type: 'symdb',
165
+ uploadId: upload_id,
166
+ batchNum: batch_num,
167
+ # Always false: the Ruby tracer continuously uploads new code
168
+ # as files are loaded; there is no defined end-of-upload point.
169
+ final: false,
170
+ attachmentSize: attachment_size,
139
171
  )
140
172
  end
141
173
 
174
+ # Return [upload_id, batch_num] for the current process. upload_id is
175
+ # generated lazily on first use and shared by all batches uploaded from
176
+ # the process. A forked child observes a different Process.pid and
177
+ # therefore gets a fresh upload_id and batch counter.
178
+ # Synchronized: ScopeBatcher releases its mutex before calling
179
+ # upload_scopes, so this can be entered concurrently.
180
+ # @return [Array<(String, Integer)>]
181
+ def next_upload_metadata
182
+ @metadata_mutex.synchronize do
183
+ if @upload_pid != Process.pid
184
+ @upload_pid = Process.pid
185
+ @upload_id = SecureRandom.uuid.freeze
186
+ @batch_num = 0
187
+ end
188
+ @batch_num += 1 # steep:ignore NoMethod
189
+ # @upload_id and @batch_num are non-nil after the branch above; refine for Steep.
190
+ upload_id = @upload_id or raise('unreachable: @upload_id should be set')
191
+ batch_num = @batch_num or raise('unreachable: @batch_num should be set')
192
+ [upload_id, batch_num]
193
+ end
194
+ end
195
+
142
196
  # Handle HTTP response and track metrics.
143
197
  # @param response [Core::Transport::Response] HTTP response from agent
144
198
  # @param scope_count [Integer] Number of scopes uploaded
@@ -36,7 +36,10 @@ module Datadog
36
36
 
37
37
  def on_start(span, _event, _id, payload)
38
38
  channel = payload[:broadcasting] # Channel has high cardinality
39
- span.service = configuration[:service_name] if configuration[:service_name]
39
+ if configuration[:service_name]
40
+ span.service = configuration[:service_name]
41
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
42
+ end
40
43
  span.type = span_type
41
44
 
42
45
  # Set analytics sample rate
@@ -37,7 +37,10 @@ module Datadog
37
37
  channel_class = payload[:channel_class]
38
38
  action = payload[:action]
39
39
 
40
- span.service = configuration[:service_name] if configuration[:service_name]
40
+ if configuration[:service_name]
41
+ span.service = configuration[:service_name]
42
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
43
+ end
41
44
  span.resource = "#{channel_class}##{action}"
42
45
  span.type = span_type
43
46
 
@@ -36,7 +36,10 @@ module Datadog
36
36
  def on_start(span, _event, _id, payload)
37
37
  channel_class = payload[:channel_class]
38
38
 
39
- span.service = configuration[:service_name] if configuration[:service_name]
39
+ if configuration[:service_name]
40
+ span.service = configuration[:service_name]
41
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
42
+ end
40
43
  span.resource = channel_class
41
44
  span.type = span_type
42
45
 
@@ -57,7 +57,10 @@ module Datadog
57
57
  configuration = Datadog.configuration.tracing[:action_cable]
58
58
 
59
59
  Tracing.trace("action_cable.#{hook}") do |span|
60
- span.service = configuration[:service_name] if configuration[:service_name]
60
+ if configuration[:service_name]
61
+ span.service = configuration[:service_name]
62
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
63
+ end
61
64
  span.resource = "#{channel.class}##{hook}"
62
65
  span.type = Tracing::Metadata::Ext::AppTypes::TYPE_WEB
63
66
 
@@ -31,7 +31,10 @@ module Datadog
31
31
  super
32
32
 
33
33
  span.type = span_type
34
- span.service = configuration[:service_name] if configuration[:service_name]
34
+ if configuration[:service_name]
35
+ span.service = configuration[:service_name]
36
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
37
+ end
35
38
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
36
39
 
37
40
  # Set analytics sample rate
@@ -42,6 +42,7 @@ module Datadog
42
42
 
43
43
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
44
44
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CONTROLLER)
45
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
45
46
  rescue => e
46
47
  Datadog.logger.error("#{e.class}: #{e.message}")
47
48
  Datadog::Core::Telemetry::Logger.report(e)
@@ -11,6 +11,8 @@ module Datadog
11
11
  module Instrumentation
12
12
  SCRIPT_NAME_KEY = 'SCRIPT_NAME'
13
13
  FORMAT_SUFFIX = '(.:format)'
14
+ # NOTE: Rails 8.1.1+ natively provides the same object via 'action_dispatch.route'.
15
+ DATADOG_RAILS_ROUTE_ENV_KEY = 'datadog.action_dispatch.route'
14
16
 
15
17
  module_function
16
18
 
@@ -48,6 +50,8 @@ module Datadog
48
50
  result.each do |_, _, route|
49
51
  next unless Instrumentation.dispatcher_route?(route)
50
52
 
53
+ req.env[DATADOG_RAILS_ROUTE_ENV_KEY] = route
54
+
51
55
  http_route = route.path.spec.to_s
52
56
  http_route.delete_suffix!(FORMAT_SUFFIX)
53
57
 
@@ -66,6 +70,8 @@ module Datadog
66
70
  def find_routes(req)
67
71
  super do |match, parameters, route|
68
72
  if Instrumentation.dispatcher_route?(route)
73
+ req.env[DATADOG_RAILS_ROUTE_ENV_KEY] = route
74
+
69
75
  http_route = route.path.spec.to_s
70
76
  http_route.delete_suffix!(FORMAT_SUFFIX)
71
77
 
@@ -86,6 +92,8 @@ module Datadog
86
92
 
87
93
  super do |route, parameters|
88
94
  if Instrumentation.dispatcher_route?(route)
95
+ req.env[DATADOG_RAILS_ROUTE_ENV_KEY] = route
96
+
89
97
  http_route = route.path.spec.to_s
90
98
  http_route = http_route.delete_suffix(FORMAT_SUFFIX)
91
99
 
@@ -28,7 +28,10 @@ module Datadog
28
28
  end
29
29
 
30
30
  def on_start(span, _event, _id, payload)
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_TEMPLATE
33
36
 
34
37
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
@@ -28,7 +28,10 @@ module Datadog
28
28
  end
29
29
 
30
30
  def on_start(span, _event, _id, payload)
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_TEMPLATE
33
36
 
34
37
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
@@ -28,7 +28,10 @@ module Datadog
28
28
 
29
29
  def on_start(span, event, _id, payload)
30
30
  span.name = span_name
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.resource = payload[:job].class.name
33
36
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_DISCARD)
34
37
 
@@ -28,7 +28,10 @@ module Datadog
28
28
 
29
29
  def on_start(span, event, _id, payload)
30
30
  span.name = span_name
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.resource = payload[:job].class.name
33
36
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ENQUEUE)
34
37
 
@@ -28,7 +28,10 @@ module Datadog
28
28
 
29
29
  def on_start(span, event, _id, payload)
30
30
  span.name = span_name
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.resource = payload[:job].class.name
33
36
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ENQUEUE_AT)
34
37
 
@@ -28,7 +28,10 @@ module Datadog
28
28
 
29
29
  def on_start(span, event, _id, payload)
30
30
  span.name = span_name
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.resource = payload[:job].class.name
33
36
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_ENQUEUE_RETRY)
34
37
 
@@ -28,7 +28,10 @@ module Datadog
28
28
 
29
29
  def on_start(span, event, _id, payload)
30
30
  span.name = span_name
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.resource = payload[:job].class.name
33
36
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_PERFORM)
34
37
 
@@ -28,7 +28,10 @@ module Datadog
28
28
 
29
29
  def on_start(span, event, _id, payload)
30
30
  span.name = span_name
31
- span.service = configuration[:service_name] if configuration[:service_name]
31
+ if configuration[:service_name]
32
+ span.service = configuration[:service_name]
33
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
34
+ end
32
35
  span.resource = payload[:job].class.name
33
36
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_RETRY_STOPPED)
34
37
 
@@ -42,16 +42,13 @@ module Datadog
42
42
 
43
43
  span.name = "#{adapter_name}.query"
44
44
  span.service = service_name
45
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
45
46
  span.resource = payload.fetch(:sql)
46
47
  span.type = Tracing::Metadata::Ext::SQL::TYPE
47
48
 
48
49
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
49
50
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_SQL)
50
51
 
51
- if service_name != Datadog.configuration.service
52
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
53
- end
54
-
55
52
  # Set analytics sample rate
56
53
  if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
57
54
  Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
@@ -77,15 +77,12 @@ module Datadog
77
77
  mapping = MAPPING.fetch(event)
78
78
 
79
79
  span.service = configuration[:cache_service]
80
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
80
81
  span.resource = mapping[:resource]
81
82
 
82
83
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
83
84
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CACHE)
84
85
 
85
- if span.service != Datadog.configuration.service
86
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
87
- end
88
-
89
86
  span.set_tag(Ext::TAG_CACHE_BACKEND, cache_backend(store))
90
87
 
91
88
  span.set_tag('EVENT', event)
@@ -51,13 +51,10 @@ module Datadog
51
51
  service: Datadog.configuration.tracing[:active_support][:cache_service],
52
52
  resource: action
53
53
  ) do |span|
54
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
54
55
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
55
56
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CACHE)
56
57
 
57
- if span.service != Datadog.configuration.service
58
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
59
- end
60
-
61
58
  span.set_tag(Ext::TAG_CACHE_BACKEND, store) if store
62
59
 
63
60
  set_cache_key(span, key, multi_key) if Datadog.configuration.tracing[:active_support][:cache_key].enabled
@@ -32,6 +32,7 @@ module Datadog
32
32
  # rubocop:disable Metrics/MethodLength
33
33
  def annotate!(span, context)
34
34
  span.service = configuration[:service_name]
35
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
35
36
  span.type = Tracing::Metadata::Ext::HTTP::TYPE_OUTBOUND
36
37
  span.name = Ext::SPAN_COMMAND
37
38
  span.resource = context.safely(:resource)
@@ -61,11 +62,6 @@ module Datadog
61
62
  )
62
63
  end
63
64
 
64
- # Tag original global service name if not used
65
- if span.service != Datadog.configuration.service
66
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
67
- end
68
-
69
65
  span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
70
66
 
71
67
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
@@ -22,6 +22,7 @@ module Datadog
22
22
  Tracing.trace(Ext::SPAN_COMMAND) do |span|
23
23
  span.resource = op.to_s.upcase
24
24
  span.service = datadog_configuration[:service_name]
25
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
25
26
  span.type = Ext::SPAN_TYPE_COMMAND
26
27
 
27
28
  if datadog_configuration[:peer_service]
@@ -31,11 +32,6 @@ module Datadog
31
32
  )
32
33
  end
33
34
 
34
- # Tag original global service name if not used
35
- if span.service != Datadog.configuration.service
36
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
37
- end
38
-
39
35
  span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
40
36
 
41
37
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
@@ -21,6 +21,7 @@ module Datadog
21
21
  resource: job_name(job),
22
22
  on_error: configuration[:on_error]
23
23
  ) do |span|
24
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
24
25
  set_sample_rate(span)
25
26
 
26
27
  # Measure service stats
@@ -51,6 +52,7 @@ module Datadog
51
52
  service: configuration[:client_service_name],
52
53
  resource: job_name(job)
53
54
  ) do |span|
55
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
54
56
  set_sample_rate(span)
55
57
 
56
58
  # Measure service stats
@@ -11,6 +11,7 @@ module Datadog
11
11
  configuration = Datadog.configuration.tracing[:delayed_job]
12
12
 
13
13
  Datadog::Tracing.trace(Ext::SPAN_RESERVE_JOB, service: configuration[:service_name]) do |span|
14
+ span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
14
15
  span.type = Datadog::Tracing::Metadata::Ext::AppTypes::TYPE_WORKER
15
16
 
16
17
  span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Ext::TAG_COMPONENT)
@@ -55,6 +55,7 @@ module Datadog
55
55
  service: service,
56
56
  on_error: on_error
57
57
  ) do |span|
58
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
58
59
  connection = transport.connections.first
59
60
  host = connection.host[:host] if connection
60
61
  port = connection.host[:port] if connection
@@ -66,11 +67,6 @@ module Datadog
66
67
  )
67
68
  end
68
69
 
69
- # Tag original global service name if not used
70
- if span.service != Datadog.configuration.service
71
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
72
- end
73
-
74
70
  span.type = Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_TYPE_QUERY
75
71
 
76
72
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../utils/quantization/hash'
3
+ require_relative '../utils/quantization/hash_formatter'
4
4
 
5
5
  module Datadog
6
6
  module Tracing
@@ -40,7 +40,7 @@ module Datadog
40
40
  # Parse each statement and quantize them.
41
41
  statements.collect do |string|
42
42
  reserialize_json(string, options[:placeholder]) do |obj|
43
- Contrib::Utils::Quantization::Hash.format(obj, options)
43
+ Contrib::Utils::Quantization::HashFormatter.format(obj, options)
44
44
  end
45
45
  end.join("\n")
46
46
  end
@@ -133,6 +133,7 @@ module Datadog
133
133
 
134
134
  def datadog_tag_request
135
135
  span = @datadog_span
136
+ span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
136
137
  method = Ext::NOT_APPLICABLE_METHOD
137
138
  method = @datadog_method.to_s if instance_variable_defined?(:@datadog_method) && !@datadog_method.nil?
138
139
  span.resource = method
@@ -144,11 +145,6 @@ module Datadog
144
145
  )
145
146
  end
146
147
 
147
- # Tag original global service name if not used
148
- if span.service != Datadog.configuration.service
149
- span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
150
- end
151
-
152
148
  # Set analytics sample rate
153
149
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
154
150
 
@@ -64,19 +64,12 @@ module Datadog
64
64
  )
65
65
  @datadog_multi_trace_digest = Tracing.active_trace.to_digest
66
66
 
67
+ @datadog_multi_span.set_tag(Tracing::Metadata::Ext::TAG_SVC_SRC, Ext::TAG_COMPONENT)
67
68
  @datadog_multi_span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
68
69
  @datadog_multi_span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_MULTI_REQUEST)
69
70
 
70
71
  @datadog_multi_span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
71
72
 
72
- # Tag original global service name if not used
73
- if @datadog_multi_span.service != Datadog.configuration.service
74
- @datadog_multi_span.set_tag(
75
- Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE,
76
- Datadog.configuration.service
77
- )
78
- end
79
-
80
73
  # Set analytics sample rate
81
74
  Contrib::Analytics.set_sample_rate(@datadog_multi_span, analytics_sample_rate) if analytics_enabled?
82
75