datadog 2.31.0 → 2.33.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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  3. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +73 -0
  4. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -1
  5. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +17 -7
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -5
  7. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +6 -0
  8. data/ext/datadog_profiling_native_extension/extconf.rb +8 -4
  9. data/ext/datadog_profiling_native_extension/http_transport.c +10 -5
  10. data/ext/datadog_profiling_native_extension/stack_recorder.c +3 -9
  11. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
  12. data/ext/libdatadog_api/crashtracker.c +2 -0
  13. data/ext/libdatadog_api/di.c +48 -0
  14. data/ext/libdatadog_api/extconf.rb +7 -4
  15. data/ext/libdatadog_extconf_helpers.rb +38 -1
  16. data/lib/datadog/ai_guard/autoload.rb +10 -0
  17. data/lib/datadog/ai_guard/component.rb +1 -1
  18. data/lib/datadog/ai_guard/configuration.rb +105 -2
  19. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  20. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  21. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  22. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +83 -0
  23. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  24. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  25. data/lib/datadog/ai_guard/evaluation.rb +2 -0
  26. data/lib/datadog/ai_guard/ext.rb +2 -0
  27. data/lib/datadog/ai_guard.rb +8 -0
  28. data/lib/datadog/appsec/autoload.rb +1 -1
  29. data/lib/datadog/appsec/component.rb +1 -1
  30. data/lib/datadog/appsec/configuration.rb +414 -1
  31. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  32. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  33. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  34. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +111 -0
  35. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
  36. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
  37. data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
  38. data/lib/datadog/appsec/metrics/telemetry.rb +13 -1
  39. data/lib/datadog/appsec/security_engine/runner.rb +1 -1
  40. data/lib/datadog/appsec/trace_keeper.rb +18 -6
  41. data/lib/datadog/appsec/utils/http/url_encoded.rb +2 -2
  42. data/lib/datadog/appsec.rb +1 -0
  43. data/lib/datadog/core/configuration/components.rb +1 -1
  44. data/lib/datadog/core/configuration/settings.rb +13 -0
  45. data/lib/datadog/core/configuration/supported_configurations.rb +4 -0
  46. data/lib/datadog/core/configuration.rb +1 -1
  47. data/lib/datadog/core/contrib/rails/utils.rb +1 -1
  48. data/lib/datadog/core/crashtracking/component.rb +3 -3
  49. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  50. data/lib/datadog/core/environment/container.rb +2 -2
  51. data/lib/datadog/core/environment/ext.rb +1 -0
  52. data/lib/datadog/core/environment/socket.rb +13 -0
  53. data/lib/datadog/core/feature_flags.rb +1 -1
  54. data/lib/datadog/core/metrics/client.rb +5 -5
  55. data/lib/datadog/core/remote/client.rb +1 -1
  56. data/lib/datadog/core/remote/component.rb +2 -2
  57. data/lib/datadog/core/runtime/metrics.rb +1 -1
  58. data/lib/datadog/core/telemetry/emitter.rb +1 -1
  59. data/lib/datadog/core/telemetry/event/app_started.rb +2 -2
  60. data/lib/datadog/core/transport/http.rb +2 -0
  61. data/lib/datadog/core/utils.rb +1 -1
  62. data/lib/datadog/core/workers/async.rb +1 -1
  63. data/lib/datadog/core.rb +1 -1
  64. data/lib/datadog/data_streams/configuration.rb +40 -1
  65. data/lib/datadog/data_streams/pathway_context.rb +1 -1
  66. data/lib/datadog/data_streams/processor.rb +1 -1
  67. data/lib/datadog/data_streams.rb +1 -1
  68. data/lib/datadog/di/base.rb +8 -5
  69. data/lib/datadog/di/code_tracker.rb +179 -1
  70. data/lib/datadog/di/component.rb +1 -1
  71. data/lib/datadog/di/configuration.rb +235 -2
  72. data/lib/datadog/di/instrumenter.rb +46 -26
  73. data/lib/datadog/di/probe_builder.rb +1 -1
  74. data/lib/datadog/di/probe_file_loader.rb +2 -2
  75. data/lib/datadog/di/probe_manager.rb +6 -6
  76. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  77. data/lib/datadog/di/probe_notifier_worker.rb +2 -2
  78. data/lib/datadog/di/remote.rb +6 -6
  79. data/lib/datadog/di/serializer.rb +1 -1
  80. data/lib/datadog/di/transport/input.rb +3 -3
  81. data/lib/datadog/error_tracking/configuration.rb +55 -2
  82. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  83. data/lib/datadog/open_feature/component.rb +18 -1
  84. data/lib/datadog/open_feature/evaluation_engine.rb +3 -3
  85. data/lib/datadog/open_feature/exposures/reporter.rb +1 -1
  86. data/lib/datadog/open_feature/exposures/worker.rb +1 -1
  87. data/lib/datadog/open_feature/hooks/flag_eval_hook.rb +49 -0
  88. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  89. data/lib/datadog/open_feature/provider.rb +19 -1
  90. data/lib/datadog/open_feature/remote.rb +1 -1
  91. data/lib/datadog/open_feature/transport.rb +1 -1
  92. data/lib/datadog/opentelemetry/metrics.rb +13 -4
  93. data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
  94. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  95. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +1 -1
  96. data/lib/datadog/profiling/collectors/code_provenance.rb +35 -9
  97. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +31 -2
  98. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +8 -2
  99. data/lib/datadog/profiling/collectors/info.rb +16 -3
  100. data/lib/datadog/profiling/component.rb +3 -6
  101. data/lib/datadog/profiling/exporter.rb +37 -12
  102. data/lib/datadog/profiling/ext.rb +0 -2
  103. data/lib/datadog/profiling/flush.rb +21 -12
  104. data/lib/datadog/profiling/http_transport.rb +12 -1
  105. data/lib/datadog/profiling/load_native_extension.rb +1 -1
  106. data/lib/datadog/profiling/profiler.rb +13 -1
  107. data/lib/datadog/profiling/scheduler.rb +2 -2
  108. data/lib/datadog/profiling/stack_recorder.rb +0 -4
  109. data/lib/datadog/profiling/tasks/exec.rb +8 -3
  110. data/lib/datadog/profiling/tasks/help.rb +1 -0
  111. data/lib/datadog/profiling/tasks/setup.rb +2 -2
  112. data/lib/datadog/single_step_instrument.rb +1 -1
  113. data/lib/datadog/symbol_database/configuration.rb +65 -0
  114. data/lib/datadog/symbol_database/extractor.rb +906 -0
  115. data/lib/datadog/symbol_database/file_hash.rb +46 -0
  116. data/lib/datadog/symbol_database/logger.rb +43 -0
  117. data/lib/datadog/symbol_database/scope.rb +102 -0
  118. data/lib/datadog/symbol_database/scope_batcher.rb +280 -0
  119. data/lib/datadog/symbol_database/service_version.rb +57 -0
  120. data/lib/datadog/symbol_database/symbol.rb +66 -0
  121. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  122. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  123. data/lib/datadog/symbol_database/transport.rb +54 -0
  124. data/lib/datadog/symbol_database/uploader.rb +169 -0
  125. data/lib/datadog/symbol_database.rb +49 -0
  126. data/lib/datadog/tracing/buffer.rb +3 -3
  127. data/lib/datadog/tracing/configuration/settings.rb +1 -1
  128. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -3
  129. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  130. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  131. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  132. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  133. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  134. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  135. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  136. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  137. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  138. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  139. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  140. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
  141. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  142. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -1
  143. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  144. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
  145. data/lib/datadog/tracing/contrib/component.rb +1 -1
  146. data/lib/datadog/tracing/contrib/configuration/resolver.rb +7 -4
  147. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  148. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
  149. data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
  150. data/lib/datadog/tracing/contrib/extensions.rb +9 -0
  151. data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
  152. data/lib/datadog/tracing/contrib/grape/endpoint.rb +5 -5
  153. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
  154. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +2 -2
  155. data/lib/datadog/tracing/contrib/http/instrumentation.rb +2 -2
  156. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -2
  157. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +2 -2
  158. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
  159. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
  160. data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
  161. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +3 -3
  162. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
  163. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -3
  164. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +6 -0
  165. data/lib/datadog/tracing/contrib/rack/ext.rb +27 -0
  166. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  167. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  168. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +117 -1
  169. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  170. data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
  171. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
  172. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  173. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  174. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  175. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  176. data/lib/datadog/tracing/contrib.rb +8 -0
  177. data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
  178. data/lib/datadog/tracing/distributed/baggage.rb +59 -5
  179. data/lib/datadog/tracing/distributed/datadog.rb +11 -11
  180. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -1
  181. data/lib/datadog/tracing/distributed/propagation.rb +2 -2
  182. data/lib/datadog/tracing/distributed/trace_context.rb +74 -32
  183. data/lib/datadog/tracing/event.rb +1 -1
  184. data/lib/datadog/tracing/metadata/tagging.rb +2 -2
  185. data/lib/datadog/tracing/pipeline.rb +1 -1
  186. data/lib/datadog/tracing/remote.rb +1 -1
  187. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  188. data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -2
  189. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  190. data/lib/datadog/tracing/span_operation.rb +3 -3
  191. data/lib/datadog/tracing/trace_operation.rb +4 -4
  192. data/lib/datadog/tracing/tracer.rb +6 -8
  193. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  194. data/lib/datadog/tracing/workers.rb +2 -1
  195. data/lib/datadog/version.rb +1 -1
  196. metadata +33 -12
  197. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  198. data/lib/datadog/ai_guard/configuration/settings.rb +0 -113
  199. data/lib/datadog/appsec/configuration/settings.rb +0 -423
  200. data/lib/datadog/data_streams/configuration/settings.rb +0 -49
  201. data/lib/datadog/di/configuration/settings.rb +0 -243
  202. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../core/transport/request'
4
+ require_relative '../core/transport/transport'
5
+ require_relative '../core/transport/http/client'
6
+ require_relative '../core/transport/http/env'
7
+
8
+ module Datadog
9
+ module SymbolDatabase
10
+ module Transport
11
+ # Transport classes for the symbols upload endpoint.
12
+ # Mirrors the per-purpose split used by DI (`DI::Transport::Input::*`).
13
+ module Symbols
14
+ # Request wrapper carrying the multipart form for a symbols upload.
15
+ class Request < Core::Transport::Request
16
+ attr_reader :form
17
+
18
+ # @param form [Hash] Multipart form data with UploadIO objects
19
+ def initialize(form)
20
+ @form = form
21
+ # Multipart upload — no parcel; the Net adapter reads form data
22
+ # off the env directly.
23
+ super(nil)
24
+ end
25
+ end
26
+
27
+ # HTTP client for symbol database uploads.
28
+ # Extends Core::Transport::HTTP::Client to set `env.form`, which the
29
+ # Net adapter (lib/datadog/core/transport/http/adapters/net.rb) detects
30
+ # and dispatches as multipart/form-data.
31
+ class Client < Core::Transport::HTTP::Client
32
+ # @param request [Request] Symbols upload request
33
+ # @return [Core::Transport::HTTP::Env] Env with form data set
34
+ def build_env(request)
35
+ Core::Transport::HTTP::Env.new(request, form: request.form)
36
+ end
37
+ end
38
+
39
+ # Transport for the symbols upload endpoint.
40
+ class Transport < Core::Transport::Transport
41
+ self.http_client_class = Client
42
+
43
+ # Send a symbols upload to the agent.
44
+ # @param form [Hash] Multipart form data with UploadIO objects
45
+ # @return [Core::Transport::Response] Response from agent
46
+ def send_symbols(form)
47
+ request = Request.new(form)
48
+ client.send_request(:symbols, request)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'zlib'
5
+ require 'stringio'
6
+ require_relative '../core/environment/identity'
7
+ require_relative '../core/vendor/multipart-post/multipart/post/composite_read_io'
8
+ require_relative 'service_version'
9
+ require_relative 'transport/http'
10
+
11
+ module Datadog
12
+ module SymbolDatabase
13
+ # Uploads symbol database payloads to the Datadog agent via HTTP multipart.
14
+ #
15
+ # Handles the complete upload process:
16
+ # 1. Wraps scopes in ServiceVersion (adds service/env/version metadata)
17
+ # 2. Serializes to JSON
18
+ # 3. Compresses with GZIP (always, ~40:1 ratio expected)
19
+ # 4. Builds multipart form: event.json (metadata) + symbols_{pid}.json.gz (data)
20
+ # 5. POSTs to agent at /symdb/v1/input via Core::Transport::HTTP
21
+ # No retries — single attempt. Any failure is logged at debug and discarded.
22
+ #
23
+ # Uses Core::Transport::HTTP infrastructure (consistent with DI, Profiling, DataStreams).
24
+ # Headers: DD-API-KEY, Datadog-Container-ID, Datadog-Entity-ID (automatic from transport)
25
+ #
26
+ # Called by: ScopeBatcher.perform_upload (when batch ready)
27
+ # Calls: Transport::HTTP for network, Zlib for compression
28
+ #
29
+ # @api private
30
+ class Uploader
31
+ MAX_PAYLOAD_SIZE = 50 * 1024 * 1024 # 50MB
32
+
33
+ # Initialize uploader.
34
+ # @param settings [Configuration::Settings] Tracer settings (for service, env, version metadata)
35
+ # @param agent_settings [Configuration::AgentSettings] Agent connection settings
36
+ # @param logger [Logger] Logger instance
37
+ # @param telemetry [Telemetry, nil] Optional telemetry component for error reporting
38
+ def initialize(settings:, agent_settings:, logger:, telemetry: nil)
39
+ @settings = settings
40
+ @agent_settings = agent_settings
41
+ @logger = logger
42
+ @telemetry = telemetry
43
+
44
+ @transport = Transport::HTTP.symbols(
45
+ agent_settings: agent_settings,
46
+ logger: @logger,
47
+ )
48
+ end
49
+
50
+ # Upload a batch of scopes to the agent.
51
+ # Wraps in ServiceVersion, serializes to JSON, compresses with GZIP,
52
+ # builds multipart form, and POSTs to /symdb/v1/input via transport.
53
+ # No retries — single attempt, matching Python behavior.
54
+ # @param scopes [Array<Scope>] Scopes to upload
55
+ # @return [void]
56
+ def upload_scopes(scopes)
57
+ return if scopes.empty?
58
+
59
+ json_data = build_symbol_payload(scopes)
60
+ compressed_data = Zlib.gzip(json_data)
61
+
62
+ # Emitted unconditionally so the rare oversized case is observable.
63
+ @telemetry&.distribution('tracers', 'symbol_database.payload_size', compressed_data.bytesize)
64
+
65
+ # Symbols for very large applications (>50MB after gzip) are dropped:
66
+ # the upload is skipped and the customer sees no autocomplete /
67
+ # symbol probe results for those classes. Java handles the same case
68
+ # by splitting the payload across multiple requests; we have not
69
+ # implemented splitting here. Deferred for a post-MVP follow-up.
70
+ if compressed_data.bytesize > MAX_PAYLOAD_SIZE
71
+ @logger.debug { "symdb: payload too large: #{compressed_data.bytesize}/#{MAX_PAYLOAD_SIZE} bytes, skipping" }
72
+ return
73
+ end
74
+
75
+ perform_http_upload(compressed_data, scopes.size)
76
+ rescue => e
77
+ @logger.debug { "symdb: upload failed: #{e.class}: #{e.message}" }
78
+ @telemetry&.report(e, description: 'symdb: upload failed')
79
+ end
80
+
81
+ private
82
+
83
+ # Build JSON payload from scopes.
84
+ # @param scopes [Array<Scope>] Scopes to serialize
85
+ # @return [String] JSON string
86
+ def build_symbol_payload(scopes)
87
+ ServiceVersion.new(
88
+ service: @settings.service,
89
+ env: @settings.env,
90
+ version: @settings.version,
91
+ scopes: scopes,
92
+ ).to_json
93
+ end
94
+
95
+ # Perform HTTP POST with multipart form-data via transport layer.
96
+ # @param compressed_data [String] GZIP compressed JSON payload
97
+ # @param scope_count [Integer] Number of scopes (for logging)
98
+ # @return [void]
99
+ def perform_http_upload(compressed_data, scope_count)
100
+ form = build_multipart_form(compressed_data)
101
+ response = @transport.send_symbols(form)
102
+ handle_response(response, scope_count)
103
+ end
104
+
105
+ # Build multipart form-data with event metadata and compressed symbols.
106
+ # @param compressed_data [String] GZIP compressed JSON payload
107
+ # @return [Hash] Form data hash with UploadIO objects
108
+ def build_multipart_form(compressed_data)
109
+ event_io = StringIO.new(build_event_metadata)
110
+ file_io = StringIO.new(compressed_data)
111
+
112
+ event_upload = Datadog::Core::Vendor::Multipart::Post::UploadIO.new(
113
+ event_io,
114
+ 'application/json',
115
+ 'event.json',
116
+ )
117
+
118
+ file_upload = Datadog::Core::Vendor::Multipart::Post::UploadIO.new(
119
+ file_io,
120
+ 'application/gzip',
121
+ "symbols_#{Process.pid}.json.gz",
122
+ )
123
+
124
+ {
125
+ 'event' => event_upload,
126
+ 'file' => file_upload,
127
+ }
128
+ end
129
+
130
+ # Build event.json metadata part.
131
+ # @return [String] JSON string for event metadata
132
+ def build_event_metadata
133
+ JSON.generate(
134
+ ddsource: 'ruby',
135
+ service: @settings.service,
136
+ runtimeId: Datadog::Core::Environment::Identity.id,
137
+ parentId: nil, # Fork tracking deferred for MVP
138
+ type: 'symdb',
139
+ )
140
+ end
141
+
142
+ # Handle HTTP response and track metrics.
143
+ # @param response [Core::Transport::Response] HTTP response from agent
144
+ # @param scope_count [Integer] Number of scopes uploaded
145
+ # @return [Boolean] true if successful, false otherwise
146
+ def handle_response(response, scope_count)
147
+ if response.internal_error?
148
+ @logger.debug { "symdb: upload failed: #{response.error.class}: #{response.error}" } # steep:ignore NoMethod
149
+ return false
150
+ end
151
+
152
+ case response.code
153
+ when 200..299
154
+ @logger.debug { "symdb: uploaded #{scope_count} scopes successfully" }
155
+ true
156
+ when 429
157
+ @logger.debug { "symdb: upload rejected: rate limited (429)" }
158
+ false
159
+ when 500..599
160
+ @logger.debug { "symdb: upload rejected: server error (#{response.code})" }
161
+ false
162
+ else
163
+ @logger.debug { "symdb: upload rejected: #{response.code}" }
164
+ false
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ # Namespace for Datadog symbol database upload.
5
+ #
6
+ # @api private
7
+ module SymbolDatabase
8
+ # Sentinel value for unknown or unavailable minimum line number.
9
+ #
10
+ # Used for:
11
+ # 1. start_line when exact line cannot be determined (e.g., modules without methods)
12
+ # 2. Symbol line numbers for FIELD, STATIC_FIELD, ARG symbols to indicate
13
+ # the symbol is available throughout the entire enclosing scope
14
+ #
15
+ # Backend behavior: line=0 means symbol completes in every line of the scope
16
+ #
17
+ # Reference: Symbol Database Backend RFC, section "Edge Cases"
18
+ # - "We use 0 for FIELD, STATIC_FIELD and ARG. It means that the symbol
19
+ # will be completed in every line of the enclosing scope (CLASS or METHOD)."
20
+ #
21
+ # @see https://www.postgresql.org/docs/current/datatype-numeric.html
22
+ UNKNOWN_MIN_LINE = 0
23
+
24
+ # Sentinel value for unknown or unavailable maximum line number.
25
+ #
26
+ # Used for:
27
+ # 1. end_line when exact boundaries cannot be determined (e.g., modules, classes
28
+ # without methods, fallback when introspection fails)
29
+ # 2. LOCAL symbol line numbers when exact line is unknown (future feature)
30
+ #
31
+ # Value: 2147483647 (PostgreSQL signed INT_MAX, 2^31 - 1)
32
+ #
33
+ # Backend behavior:
34
+ # - For scopes: indicates "entire file" or "unknown end"
35
+ # - For LOCAL symbols (future): included in method probe completions but excluded
36
+ # from line probe completions
37
+ #
38
+ # Protocol specification:
39
+ # - "If the symbols of the scope should be available to all lines in the
40
+ # source_file of the scope, use start_line = 0 and end_line = 2147483647
41
+ # (maximum signed integer, postgres int max)."
42
+ # - "For LOCAL symbols, we use 2147483647 (signed int max) to avoid completing
43
+ # the symbol for line probes, but keep it in the method for method probe completions."
44
+ #
45
+ # Reference: Symbol Database Backend RFC, section "Scope" and "Edge Cases"
46
+ # @see https://www.postgresql.org/docs/current/datatype-numeric.html
47
+ UNKNOWN_MAX_LINE = 2147483647
48
+ end
49
+ end
@@ -56,7 +56,7 @@ module Datadog
56
56
  @buffer_spans += trace.length
57
57
  rescue => e
58
58
  Datadog.logger.debug(
59
- "Failed to measure queue accept. Cause: #{e.class}: #{e} Source: #{Array(e.backtrace).first}"
59
+ "Failed to measure queue accept. Cause: #{e.class}: #{e.message} Source: #{Array(e.backtrace).first}"
60
60
  )
61
61
  end
62
62
 
@@ -66,7 +66,7 @@ module Datadog
66
66
  @buffer_spans -= trace.length
67
67
  rescue => e
68
68
  Datadog.logger.debug(
69
- "Failed to measure queue drop. Cause: #{e.class}: #{e} Source: #{Array(e.backtrace).first}"
69
+ "Failed to measure queue drop. Cause: #{e.class}: #{e.message} Source: #{Array(e.backtrace).first}"
70
70
  )
71
71
  end
72
72
 
@@ -91,7 +91,7 @@ module Datadog
91
91
  @buffer_spans = 0
92
92
  rescue => e
93
93
  Datadog.logger.debug(
94
- "Failed to measure queue. Cause: #{e.class}: #{e} Source: #{Array(e.backtrace).first}"
94
+ "Failed to measure queue. Cause: #{e.class}: #{e.message} Source: #{Array(e.backtrace).first}"
95
95
  )
96
96
  end
97
97
  end
@@ -430,7 +430,7 @@ module Datadog
430
430
  rescue => e
431
431
  # `File#read` errors have clear and actionable messages, no need to add extra exception info.
432
432
  Datadog.logger.warn(
433
- "Cannot read span sampling rules file `#{rules_file}`: #{e.class}: #{e}." \
433
+ "Cannot read span sampling rules file `#{rules_file}`: #{e.class}: #{e.message}." \
434
434
  'No span sampling rules will be applied.'
435
435
  )
436
436
  nil
@@ -43,7 +43,7 @@ module Datadog
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
45
  rescue => e
46
- Datadog.logger.error("#{e.class}: #{e}")
46
+ Datadog.logger.error("#{e.class}: #{e.message}")
47
47
  Datadog::Core::Telemetry::Logger.report(e)
48
48
  end
49
49
 
@@ -88,7 +88,7 @@ module Datadog
88
88
  span.finish
89
89
  end
90
90
  rescue => e
91
- Datadog.logger.error("#{e.class}: #{e}")
91
+ Datadog.logger.error("#{e.class}: #{e.message}")
92
92
  Datadog::Core::Telemetry::Logger.report(e)
93
93
  end
94
94
 
@@ -121,7 +121,9 @@ module Datadog
121
121
  result
122
122
  # rubocop:disable Lint/RescueException
123
123
  rescue Exception => e
124
- payload[:exception] = [e.class.name, e.message]
124
+ # Rails ActiveSupport::Notifications convention — payload[:exception] is
125
+ # an array of [class_name_string, message_string] consumed by subscribers.
126
+ payload[:exception] = [e.class.name, e.message] # rubocop:disable CustomCops/ExceptionMessageCop
125
127
  payload[:exception_object] = e
126
128
  raise e
127
129
  ensure
@@ -47,7 +47,7 @@ module Datadog
47
47
 
48
48
  record_exception(span, payload)
49
49
  rescue => e
50
- Datadog.logger.debug { "#{e.class}: #{e}" }
50
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
51
51
  end
52
52
  end
53
53
  end
@@ -40,7 +40,7 @@ module Datadog
40
40
  set_common_tags(span, payload)
41
41
  span.set_tag(Ext::TAG_JOB_ERROR, payload[:error])
42
42
  rescue => e
43
- Datadog.logger.debug { "#{e.class}: #{e}" }
43
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
44
44
  end
45
45
  end
46
46
  end
@@ -39,7 +39,7 @@ module Datadog
39
39
 
40
40
  set_common_tags(span, payload)
41
41
  rescue => e
42
- Datadog.logger.debug { "#{e.class}: #{e}" }
42
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
43
43
  end
44
44
  end
45
45
  end
@@ -39,7 +39,7 @@ module Datadog
39
39
 
40
40
  set_common_tags(span, payload)
41
41
  rescue => e
42
- Datadog.logger.debug { "#{e.class}: #{e}" }
42
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
43
43
  end
44
44
  end
45
45
  end
@@ -41,7 +41,7 @@ module Datadog
41
41
  span.set_tag(Ext::TAG_JOB_ERROR, payload[:error])
42
42
  span.set_tag(Ext::TAG_JOB_RETRY_WAIT, payload[:wait])
43
43
  rescue => e
44
- Datadog.logger.debug { "#{e.class}: #{e}" }
44
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
45
45
  end
46
46
  end
47
47
  end
@@ -39,7 +39,7 @@ module Datadog
39
39
 
40
40
  set_common_tags(span, payload)
41
41
  rescue => e
42
- Datadog.logger.debug { "#{e.class}: #{e}" }
42
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
43
43
  end
44
44
  end
45
45
  end
@@ -40,7 +40,7 @@ module Datadog
40
40
  set_common_tags(span, payload)
41
41
  span.set_tag(Ext::TAG_JOB_ERROR, payload[:error])
42
42
  rescue => e
43
- Datadog.logger.debug { "#{e.class}: #{e}" }
43
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
44
44
  end
45
45
  end
46
46
  end
@@ -35,7 +35,7 @@ module Datadog
35
35
 
36
36
  set_common_tags(span, payload)
37
37
  rescue => e
38
- Datadog.logger.debug { "#{e.class}: #{e}" }
38
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
39
39
  end
40
40
  end
41
41
  end
@@ -37,7 +37,7 @@ module Datadog
37
37
 
38
38
  set_common_tags(span, payload)
39
39
  rescue => e
40
- Datadog.logger.debug { "#{e.class}: #{e}" }
40
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
41
41
  end
42
42
  end
43
43
  end
@@ -76,7 +76,7 @@ module Datadog
76
76
  #
77
77
  Datadog.logger.error(
78
78
  'Failed to resolve ActiveRecord database configuration. ' \
79
- "Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
79
+ "Cause: #{e.class} Source: #{Array(e.backtrace).first}"
80
80
  )
81
81
  Core::Telemetry::Logger.report(e, description: 'Failed to resolve ActiveRecord database configuration')
82
82
 
@@ -96,7 +96,7 @@ module Datadog
96
96
  rescue => e
97
97
  Datadog.logger.error(
98
98
  "Failed to resolve key #{matcher.inspect}. " \
99
- "Cause: #{e.class.name} Source: #{Array(e.backtrace).first}"
99
+ "Cause: #{e.class} Source: #{Array(e.backtrace).first}"
100
100
  )
101
101
  Core::Telemetry::Logger.report(e, description: 'Failed to resolve key')
102
102
 
@@ -49,7 +49,7 @@ module Datadog
49
49
  span.set_tag(Ext::TAG_INSTANTIATION_CLASS_NAME, payload.fetch(:class_name))
50
50
  span.set_tag(Ext::TAG_INSTANTIATION_RECORD_COUNT, payload.fetch(:record_count))
51
51
  rescue => e
52
- Datadog.logger.error("#{e.class}: #{e}")
52
+ Datadog.logger.error("#{e.class}: #{e.message}")
53
53
  Datadog::Core::Telemetry::Logger.report(e)
54
54
  end
55
55
  end
@@ -69,7 +69,7 @@ module Datadog
69
69
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, config[:host]) if config[:host]
70
70
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, config[:port]) if config[:port]
71
71
  rescue => e
72
- Datadog.logger.error("#{e.class}: #{e}")
72
+ Datadog.logger.error("#{e.class}: #{e.message}")
73
73
  Datadog::Core::Telemetry::Logger.report(e)
74
74
  end
75
75
  end
@@ -77,7 +77,7 @@ module Datadog
77
77
  # in case.
78
78
  Datadog.logger.debug(
79
79
  "connection_id #{connection_id} does not represent a valid object. " \
80
- "Cause: #{e.class}: #{e} Source: #{Array(e.backtrace).first}"
80
+ "Cause: #{e.class}: #{e.message} Source: #{Array(e.backtrace).first}"
81
81
  )
82
82
  end
83
83
  else
@@ -94,7 +94,7 @@ module Datadog
94
94
  set_cache_key(span, key, mapping[:multi_key])
95
95
  end
96
96
  rescue => e
97
- Datadog.logger.error("#{e.class}: #{e}")
97
+ Datadog.logger.error("#{e.class}: #{e.message}")
98
98
  Datadog::Core::Telemetry::Logger.report(e)
99
99
  end
100
100
 
@@ -125,7 +125,7 @@ module Datadog
125
125
  @block&.call(span, name, id, payload)
126
126
  rescue => e
127
127
  Datadog.logger.debug(
128
- "ActiveSupport::Notifications handler for '#{name}' failed: #{e.class}: #{e}"
128
+ "ActiveSupport::Notifications handler for '#{name}' failed: #{e.class}: #{e.message}"
129
129
  )
130
130
  end
131
131
  end
@@ -147,7 +147,7 @@ module Datadog
147
147
  callback.call(event, key, *args)
148
148
  rescue => e
149
149
  Datadog.logger.debug(
150
- "ActiveSupport::Notifications '#{key}' callback for '#{event}' failed: #{e.class}: #{e}"
150
+ "ActiveSupport::Notifications '#{key}' callback for '#{event}' failed: #{e.class}: #{e.message}"
151
151
  )
152
152
  end
153
153
  end
@@ -90,7 +90,7 @@ module Datadog
90
90
 
91
91
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
92
92
  rescue => e
93
- Datadog.logger.error("#{e.class}: #{e}")
93
+ Datadog.logger.error("#{e.class}: #{e.message}")
94
94
  Datadog::Core::Telemetry::Logger.report(e)
95
95
  end
96
96
  # rubocop:enable Metrics/MethodLength
@@ -20,7 +20,7 @@ module Datadog
20
20
  @registry.each do |name, callback|
21
21
  callback.call(config)
22
22
  rescue => e
23
- Datadog.logger.warn("Error configuring integration #{name}: #{e}")
23
+ Datadog.logger.warn("Error configuring integration #{name}: #{e.class}: #{e.message}")
24
24
  end
25
25
  end
26
26
 
@@ -95,14 +95,17 @@ module Datadog
95
95
  super(*args)
96
96
 
97
97
  @cache_limit = cache_limit
98
- @cache = {}
98
+ # Workaround for Ruby VM < 3.2.8, < 3.3.8 and < 3.4.3 (see https://bugs.ruby-lang.org/issues/21170)
99
+ # We initialize the hash with 10 dummy entries + clear it to force Ruby to use an
100
+ # "st_table" representation for the Hash, not an "ar_table" (since Ruby will not
101
+ # shrink a Hash using an "st_table" back to an "ar_table")
102
+ @cache = Hash[*1..20]
103
+ @cache.clear
99
104
  end
100
105
 
101
106
  # (see Resolver#resolve)
102
107
  def resolve(value)
103
- if @cache.key?(value)
104
- @cache[value]
105
- else
108
+ @cache.fetch(value) do
106
109
  if @cache.size >= @cache_limit
107
110
  @cache.shift # Remove the oldest entry if cache is full
108
111
  end
@@ -16,7 +16,7 @@ module Datadog
16
16
  command = Core::Utils.utf8_encode(command, binary: true, placeholder: placeholder)
17
17
  Core::Utils.truncate(command, Ext::QUANTIZE_MAX_CMD_LENGTH)
18
18
  rescue => e
19
- Datadog.logger.debug("Error sanitizing Dalli operation: #{e}")
19
+ Datadog.logger.debug("Error sanitizing Dalli operation: #{e.class}: #{e.message}")
20
20
  placeholder
21
21
  end
22
22
  end
@@ -98,7 +98,7 @@ module Datadog
98
98
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
99
99
  rescue => e
100
100
  # TODO: Refactor the code to streamline the execution without ensure
101
- Datadog.logger.error("#{e.class}: #{e}")
101
+ Datadog.logger.error("#{e.class}: #{e.message}")
102
102
  Datadog::Core::Telemetry::Logger.report(e)
103
103
  ensure
104
104
  # the call is still executed
@@ -40,7 +40,7 @@ module Datadog
40
40
  span
41
41
  end
42
42
  rescue => e
43
- Datadog.logger.debug { "#{e.class}: #{e}" }
43
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
44
44
  end
45
45
 
46
46
  @stack.request_call(datum)
@@ -180,7 +180,7 @@ module Datadog
180
180
  end
181
181
  end
182
182
  rescue => e
183
- Datadog.logger.debug { "#{e.class}: #{e}" }
183
+ Datadog.logger.debug { "#{e.class}: #{e.message}" }
184
184
  end
185
185
 
186
186
  def propagate!(trace, span, datum)
@@ -227,6 +227,15 @@ module Datadog
227
227
  end
228
228
  end
229
229
 
230
+ # Returns the subset of built-in integrations that are instrumented,
231
+ # excluding custom integrations registered through the public contrib API.
232
+ # This method is only for telemetry reporting.
233
+ # @!visibility private
234
+ def instrumented_built_in_integrations
235
+ instrumented = Set.new(instrumented_integrations.each_value)
236
+ Contrib::BUILT_IN_INTEGRATIONS.select { |integration| instrumented.include?(integration) }.freeze
237
+ end
238
+
230
239
  # @!visibility private
231
240
  def reset!
232
241
  INSTRUMENTED_INTEGRATIONS_LOCK.synchronize do
@@ -83,7 +83,7 @@ module Datadog
83
83
 
84
84
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
85
85
  rescue => e
86
- Datadog.logger.error("#{e.class}: #{e}")
86
+ Datadog.logger.error("#{e.class}: #{e.message}")
87
87
  Datadog::Core::Telemetry::Logger.report(e)
88
88
  end
89
89
  # rubocop:enable Metrics/AbcSize
@@ -98,7 +98,7 @@ module Datadog
98
98
  Datadog.configuration.tracing.header_tags.response_tags(env[:response_headers])
99
99
  )
100
100
  rescue => e
101
- Datadog.logger.error("#{e.class}: #{e}")
101
+ Datadog.logger.error("#{e.class}: #{e.message}")
102
102
  Datadog::Core::Telemetry::Logger.report(e)
103
103
  end
104
104
  # rubocop:enable Metrics/AbcSize