datadog 2.2.0 → 2.4.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 (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +87 -2
  3. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
  4. data/ext/datadog_profiling_loader/extconf.rb +14 -26
  5. data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
  6. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
  7. data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
  8. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +257 -69
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +53 -28
  10. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
  11. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
  12. data/ext/datadog_profiling_native_extension/collectors_stack.c +136 -81
  13. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +661 -48
  15. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -1
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +83 -0
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +53 -0
  18. data/ext/datadog_profiling_native_extension/extconf.rb +91 -69
  19. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
  20. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
  21. data/ext/datadog_profiling_native_extension/heap_recorder.c +54 -12
  22. data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
  23. data/ext/datadog_profiling_native_extension/helpers.h +6 -17
  24. data/ext/datadog_profiling_native_extension/http_transport.c +41 -9
  25. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
  27. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -172
  28. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +116 -139
  29. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +20 -11
  30. data/ext/datadog_profiling_native_extension/profiling.c +1 -3
  31. data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
  32. data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
  33. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
  34. data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
  35. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
  36. data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
  37. data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
  38. data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +37 -22
  39. data/ext/libdatadog_api/datadog_ruby_common.c +83 -0
  40. data/ext/libdatadog_api/datadog_ruby_common.h +53 -0
  41. data/ext/libdatadog_api/extconf.rb +108 -0
  42. data/ext/libdatadog_api/macos_development.md +26 -0
  43. data/ext/libdatadog_extconf_helpers.rb +130 -0
  44. data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
  45. data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
  46. data/lib/datadog/appsec/component.rb +29 -8
  47. data/lib/datadog/appsec/configuration/settings.rb +2 -2
  48. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
  49. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
  50. data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
  51. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +35 -0
  52. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
  53. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +71 -0
  54. data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -0
  55. data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
  56. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
  57. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +3 -6
  58. data/lib/datadog/appsec/event.rb +1 -1
  59. data/lib/datadog/appsec/processor/actions.rb +1 -1
  60. data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
  61. data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
  62. data/lib/datadog/appsec/processor.rb +36 -37
  63. data/lib/datadog/appsec/rate_limiter.rb +25 -40
  64. data/lib/datadog/appsec/remote.rb +7 -3
  65. data/lib/datadog/appsec/response.rb +15 -1
  66. data/lib/datadog/appsec.rb +3 -2
  67. data/lib/datadog/core/configuration/components.rb +18 -15
  68. data/lib/datadog/core/configuration/settings.rb +135 -9
  69. data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
  70. data/lib/datadog/core/crashtracking/component.rb +111 -0
  71. data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
  72. data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
  73. data/lib/datadog/core/environment/execution.rb +5 -5
  74. data/lib/datadog/core/metrics/client.rb +7 -0
  75. data/lib/datadog/core/rate_limiter.rb +183 -0
  76. data/lib/datadog/core/remote/client/capabilities.rb +4 -3
  77. data/lib/datadog/core/remote/component.rb +4 -2
  78. data/lib/datadog/core/remote/negotiation.rb +4 -4
  79. data/lib/datadog/core/remote/tie.rb +2 -0
  80. data/lib/datadog/core/runtime/metrics.rb +1 -1
  81. data/lib/datadog/core/telemetry/component.rb +51 -2
  82. data/lib/datadog/core/telemetry/emitter.rb +9 -11
  83. data/lib/datadog/core/telemetry/event.rb +37 -1
  84. data/lib/datadog/core/telemetry/ext.rb +1 -0
  85. data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
  86. data/lib/datadog/core/telemetry/http/ext.rb +3 -0
  87. data/lib/datadog/core/telemetry/http/transport.rb +38 -9
  88. data/lib/datadog/core/telemetry/logger.rb +51 -0
  89. data/lib/datadog/core/telemetry/logging.rb +71 -0
  90. data/lib/datadog/core/telemetry/request.rb +13 -1
  91. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
  92. data/lib/datadog/core/utils/time.rb +12 -0
  93. data/lib/datadog/di/code_tracker.rb +168 -0
  94. data/lib/datadog/di/configuration/settings.rb +163 -0
  95. data/lib/datadog/di/configuration.rb +11 -0
  96. data/lib/datadog/di/error.rb +31 -0
  97. data/lib/datadog/di/extensions.rb +16 -0
  98. data/lib/datadog/di/probe.rb +133 -0
  99. data/lib/datadog/di/probe_builder.rb +41 -0
  100. data/lib/datadog/di/redactor.rb +188 -0
  101. data/lib/datadog/di/serializer.rb +193 -0
  102. data/lib/datadog/di.rb +14 -0
  103. data/lib/datadog/kit/appsec/events.rb +2 -4
  104. data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
  105. data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
  106. data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
  107. data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
  108. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +28 -26
  109. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
  110. data/lib/datadog/profiling/collectors/info.rb +15 -6
  111. data/lib/datadog/profiling/collectors/thread_context.rb +30 -2
  112. data/lib/datadog/profiling/component.rb +89 -95
  113. data/lib/datadog/profiling/exporter.rb +3 -3
  114. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
  115. data/lib/datadog/profiling/ext.rb +21 -21
  116. data/lib/datadog/profiling/flush.rb +1 -1
  117. data/lib/datadog/profiling/http_transport.rb +14 -7
  118. data/lib/datadog/profiling/load_native_extension.rb +5 -5
  119. data/lib/datadog/profiling/preload.rb +1 -1
  120. data/lib/datadog/profiling/profiler.rb +5 -8
  121. data/lib/datadog/profiling/scheduler.rb +33 -25
  122. data/lib/datadog/profiling/stack_recorder.rb +3 -0
  123. data/lib/datadog/profiling/tag_builder.rb +2 -2
  124. data/lib/datadog/profiling/tasks/exec.rb +5 -5
  125. data/lib/datadog/profiling/tasks/setup.rb +16 -35
  126. data/lib/datadog/profiling.rb +4 -5
  127. data/lib/datadog/single_step_instrument.rb +12 -0
  128. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
  129. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
  130. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
  131. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
  132. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
  133. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
  134. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
  135. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +4 -1
  136. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
  137. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
  138. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  139. data/lib/datadog/tracing/contrib/ext.rb +14 -0
  140. data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
  141. data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
  142. data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
  143. data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
  144. data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
  145. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +14 -10
  146. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +10 -4
  147. data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
  148. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
  149. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
  150. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
  151. data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
  152. data/lib/datadog/tracing/contrib/lograge/patcher.rb +15 -0
  153. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  154. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  155. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
  156. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
  157. data/lib/datadog/tracing/contrib/patcher.rb +2 -1
  158. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
  159. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
  160. data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
  161. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
  162. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
  163. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
  164. data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
  165. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
  166. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
  167. data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
  168. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
  169. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
  170. data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
  171. data/lib/datadog/tracing/distributed/propagation.rb +7 -0
  172. data/lib/datadog/tracing/metadata/errors.rb +9 -1
  173. data/lib/datadog/tracing/metadata/ext.rb +6 -0
  174. data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
  175. data/lib/datadog/tracing/remote.rb +5 -2
  176. data/lib/datadog/tracing/sampling/matcher.rb +6 -1
  177. data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
  178. data/lib/datadog/tracing/sampling/rule.rb +2 -0
  179. data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
  180. data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
  181. data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
  182. data/lib/datadog/tracing/span.rb +9 -2
  183. data/lib/datadog/tracing/span_event.rb +41 -0
  184. data/lib/datadog/tracing/span_operation.rb +6 -2
  185. data/lib/datadog/tracing/trace_operation.rb +26 -2
  186. data/lib/datadog/tracing/tracer.rb +14 -12
  187. data/lib/datadog/tracing/transport/http/client.rb +1 -0
  188. data/lib/datadog/tracing/transport/io/client.rb +1 -0
  189. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
  190. data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
  191. data/lib/datadog/tracing/workers.rb +1 -1
  192. data/lib/datadog/version.rb +1 -1
  193. metadata +46 -11
  194. data/lib/datadog/profiling/crashtracker.rb +0 -91
  195. data/lib/datadog/profiling/ext/forking.rb +0 -98
  196. data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -114,7 +114,10 @@ module Datadog
114
114
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
115
115
 
116
116
  if sql
117
- propagation_mode = Contrib::Propagation::SqlComment::Mode.new(comment_propagation)
117
+ propagation_mode = Contrib::Propagation::SqlComment::Mode.new(
118
+ comment_propagation,
119
+ datadog_configuration[:append_comment]
120
+ )
118
121
  Contrib::Propagation::SqlComment.annotate!(span, propagation_mode)
119
122
  propagated_sql_statement = Contrib::Propagation::SqlComment.prepend_comment(
120
123
  sql,
@@ -13,22 +13,10 @@ module Datadog
13
13
  module Patcher
14
14
  include Contrib::Patcher
15
15
 
16
- PATCH_ONLY_ONCE = Core::Utils::OnlyOnce.new
17
-
18
16
  module_function
19
17
 
20
- def patched?
21
- PATCH_ONLY_ONCE.ran?
22
- end
23
-
24
18
  def patch
25
- PATCH_ONLY_ONCE.run do
26
- begin
27
- ::Presto::Client::Client.include(Instrumentation::Client)
28
- rescue StandardError => e
29
- Datadog.logger.error("Unable to apply Presto integration: #{e}")
30
- end
31
- end
19
+ ::Presto::Client::Client.include(Instrumentation::Client)
32
20
  end
33
21
  end
34
22
  end
@@ -20,10 +20,38 @@ module Datadog
20
20
  # The value should be `true` when `full` mode
21
21
  TAG_DBM_TRACE_INJECTED = '_dd.dbm_trace_injected'
22
22
 
23
+ # Database service/sql span service (i.e. the service executing the actual query)
24
+ #
25
+ # If fake services are disabled:
26
+ # This value will be the same as the parent service
27
+ #
28
+ # If fake services are enabled:
29
+ # This value is NOT the same as the parent service
30
+ #
31
+ # This should NOT be overridden by peer.service.
23
32
  KEY_DATABASE_SERVICE = 'dddbs'
33
+
34
+ # The global service environment (e.g. DD_ENV)
24
35
  KEY_ENVIRONMENT = 'dde'
36
+
37
+ # The global service name (e.g. DD_SERVICE)
25
38
  KEY_PARENT_SERVICE = 'ddps'
39
+
40
+ # The global service version (e.g. DD_VERSION)
26
41
  KEY_VERSION = 'ddpv'
42
+
43
+ # The hostname of the database server, as provided to the database client upon instantiation.
44
+ # @see Datadog::Tracing::Metadata::Ext::TAG_PEER_HOSTNAME
45
+ KEY_HOSTNAME = 'ddh'
46
+
47
+ # @see Datadog::Tracing::Contrib::Ext::DB::TAG_INSTANCE
48
+ KEY_DB_NAME = 'dddb'
49
+
50
+ # Users can use this attribute to specify the identity of the dependency/database they are connecting to.
51
+ # We should grab this attribute only if the user is EXPLICITLY specifying it.
52
+ # @see Datadog::Tracing::Metadata::Ext::TAG_PEER_SERVICE
53
+ KEY_PEER_SERVICE = 'ddprs'
54
+
27
55
  KEY_TRACEPARENT = 'traceparent'
28
56
  end
29
57
  end
@@ -8,7 +8,7 @@ module Datadog
8
8
  module Propagation
9
9
  # Implements sql comment propagation related contracts.
10
10
  module SqlComment
11
- Mode = Struct.new(:mode) do
11
+ Mode = Struct.new(:mode, :append) do
12
12
  def enabled?
13
13
  service? || full?
14
14
  end
@@ -20,6 +20,10 @@ module Datadog
20
20
  def full?
21
21
  mode == Ext::FULL
22
22
  end
23
+
24
+ def append?
25
+ append
26
+ end
23
27
  end
24
28
  end
25
29
  end
@@ -22,16 +22,28 @@ module Datadog
22
22
  def self.prepend_comment(sql, span_op, trace_op, mode)
23
23
  return sql unless mode.enabled?
24
24
 
25
+ config = Datadog.configuration
26
+
27
+ parent_service = config.service
28
+ peer_service = span_op.get_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE)
29
+
25
30
  tags = {
26
- Ext::KEY_DATABASE_SERVICE => span_op.get_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE) || span_op.service,
27
- Ext::KEY_ENVIRONMENT => datadog_configuration.env,
28
- Ext::KEY_PARENT_SERVICE => datadog_configuration.service,
29
- Ext::KEY_VERSION => datadog_configuration.version
31
+ Ext::KEY_ENVIRONMENT => config.env,
32
+ Ext::KEY_PARENT_SERVICE => parent_service,
33
+ Ext::KEY_VERSION => config.version,
34
+ Ext::KEY_HOSTNAME => span_op.get_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME),
35
+ Ext::KEY_DB_NAME => span_op.get_tag(Contrib::Ext::DB::TAG_INSTANCE),
36
+ Ext::KEY_PEER_SERVICE => peer_service,
30
37
  }
31
38
 
39
+ db_service = peer_service || span_op.service
40
+ if parent_service != db_service # Only set if it's different from parent_service; otherwise it's redundant
41
+ tags[Ext::KEY_DATABASE_SERVICE] = db_service
42
+ end
43
+
32
44
  if mode.full?
33
45
  # When tracing is disabled, trace_operation is a dummy object that does not contain data to build traceparent
34
- if datadog_configuration.tracing.enabled
46
+ if config.tracing.enabled
35
47
  tags[Ext::KEY_TRACEPARENT] =
36
48
  Tracing::Distributed::TraceContext.new(fetcher: nil).send(:build_traceparent, trace_op.to_digest)
37
49
  else
@@ -42,11 +54,11 @@ module Datadog
42
54
  end
43
55
  end
44
56
 
45
- "#{Comment.new(tags)} #{sql}"
46
- end
47
-
48
- def self.datadog_configuration
49
- Datadog.configuration
57
+ if mode.append?
58
+ "#{sql} #{Comment.new(tags)}"
59
+ else
60
+ "#{Comment.new(tags)} #{sql}"
61
+ end
50
62
  end
51
63
  end
52
64
  end
@@ -138,6 +138,29 @@ module Datadog
138
138
  request_span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_REQUEST)
139
139
  request_span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_SERVER)
140
140
 
141
+ if status != 404 && (last_route = trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE))
142
+ last_script_name = trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH) || ''
143
+
144
+ # If the last_script_name is empty but the env['SCRIPT_NAME'] is NOT empty
145
+ # then the current rack request was not routed and must be accounted for
146
+ # which only happens in pure nested rack requests i.e /rack/rack/hello/world
147
+ #
148
+ # To account for the unaccounted nested rack requests of /rack/hello/world,
149
+ # we use 'PATH_INFO knowing that rack cannot have named parameters
150
+ if last_script_name == '' && env['SCRIPT_NAME'] && env['SCRIPT_NAME'] != ''
151
+ last_script_name = last_route
152
+ last_route = env['PATH_INFO']
153
+ end
154
+
155
+ # Clear the route and route path tags from the request trace to avoid possibility of misplacement
156
+ trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE)
157
+ trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
158
+
159
+ # Ensure tags are placed in rack.request span as desired
160
+ request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, last_script_name + last_route)
161
+ request_span.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
162
+ end
163
+
141
164
  # Set analytics sample rate
142
165
  if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
143
166
  Contrib::Analytics.set_sample_rate(request_span, configuration[:analytics_sample_rate])
@@ -195,6 +218,10 @@ module Datadog
195
218
  request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_USER_AGENT, user_agent)
196
219
  end
197
220
 
221
+ if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE).nil? && status != 404
222
+ request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, env['PATH_INFO'])
223
+ end
224
+
198
225
  HeaderTagging.tag_request_headers(request_span, request_header_collection, configuration)
199
226
  HeaderTagging.tag_response_headers(request_span, headers, configuration) if headers
200
227
 
@@ -4,6 +4,7 @@ require_relative '../../metadata/ext'
4
4
  require_relative '../analytics'
5
5
  require_relative 'ext'
6
6
  require_relative '../ext'
7
+ require_relative '../../../core/telemetry/logger'
7
8
 
8
9
  module Datadog
9
10
  module Tracing
@@ -45,6 +46,9 @@ module Datadog
45
46
  span.set_tag Ext::TAG_RAW_COMMAND, raw_command
46
47
 
47
48
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
49
+ rescue StandardError => e
50
+ Datadog.logger.error(e.message)
51
+ Datadog::Core::Telemetry::Logger.report(e)
48
52
  end
49
53
 
50
54
  private
@@ -69,6 +69,10 @@ module Datadog
69
69
 
70
70
  trace.resource = span.resource
71
71
 
72
+ _, path = env['sinatra.route'].split(' ', 2)
73
+ trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, path)
74
+ trace.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH, env['SCRIPT_NAME'])
75
+
72
76
  sinatra_request_span = Sinatra::Env.datadog_span(env)
73
77
 
74
78
  sinatra_request_span.resource = span.resource
@@ -47,8 +47,9 @@ module Datadog
47
47
 
48
48
  # Measure service stats
49
49
  Contrib::Analytics.set_measured(span)
50
-
51
- span.set_tag(Ext::TAG_REQUEST_ID, event.request_id)
50
+ # `5.38.0` Add request_id to RequestEndEvent
51
+ # https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md#5380---2021-08-10
52
+ span.set_tag(Ext::TAG_REQUEST_ID, event.request_id) if event.respond_to?(:request_id)
52
53
  span.set_tag(Ext::TAG_REQUEST_HTTP_STATUS, event.http_status.to_s)
53
54
  span.set_tag(Ext::TAG_REQUEST_METHOD, event.method)
54
55
  span.set_tag(Ext::TAG_REQUEST_PATH, event.path)
@@ -46,6 +46,11 @@ module Datadog
46
46
  o.default Contrib::Propagation::SqlComment::Ext::DISABLED
47
47
  end
48
48
 
49
+ option :append_comment do |o|
50
+ o.type :bool
51
+ o.default false
52
+ end
53
+
49
54
  option :peer_service do |o|
50
55
  o.type :string, nilable: true
51
56
  o.env Ext::ENV_PEER_SERVICE
@@ -49,13 +49,16 @@ module Datadog
49
49
  # Set analytics sample rate
50
50
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
51
51
 
52
+ span.set_tag(Contrib::Ext::DB::TAG_INSTANCE, connection_options[:database])
52
53
  span.set_tag(Ext::TAG_DB_NAME, connection_options[:database])
53
54
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, connection_options[:host])
54
55
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, connection_options[:port])
55
56
 
56
57
  Contrib::SpanAttributeSchema.set_peer_service!(span, Ext::PEER_SERVICE_SOURCES)
57
58
 
58
- propagation_mode = Contrib::Propagation::SqlComment::Mode.new(comment_propagation)
59
+ propagation_mode = Contrib::Propagation::SqlComment::Mode.new(
60
+ comment_propagation, datadog_configuration[:append_comment]
61
+ )
59
62
 
60
63
  Contrib::Propagation::SqlComment.annotate!(span, propagation_mode)
61
64
  sql = Contrib::Propagation::SqlComment.prepend_comment(
@@ -14,8 +14,8 @@ module Datadog
14
14
 
15
15
  def self.collect_and_log!(responses: nil)
16
16
  if log?
17
- env_data = EnvironmentCollector.collect_config!
18
- log_configuration!('TRACING', env_data.to_json)
17
+ log_configuration!('TRACING', EnvironmentCollector.collect_config!.to_json)
18
+ log_debug!('TRACING INTEGRATIONS', EnvironmentCollector.collect_integrations_settings!.to_json)
19
19
 
20
20
  if responses
21
21
  err_data = EnvironmentCollector.collect_errors!(responses)
@@ -40,7 +40,6 @@ module Datadog
40
40
  sampling_rules: sampling_rules,
41
41
  integrations_loaded: integrations_loaded,
42
42
  partial_flushing_enabled: partial_flushing_enabled,
43
- **instrumented_integrations_settings
44
43
  }
45
44
  end
46
45
 
@@ -128,6 +127,18 @@ module Datadog
128
127
  !!Datadog.configuration.tracing.partial_flush.enabled
129
128
  end
130
129
 
130
+ def collect_integrations_settings!
131
+ instrumented_integrations.each_with_object({}) do |(name, integration), result|
132
+ integration.configuration.to_h.each do |setting, value|
133
+ next if setting == :tracer # Skip internal objects
134
+
135
+ # Convert value to a string to avoid custom #to_json
136
+ # handlers possibly causing errors.
137
+ result[:"#{name}_#{setting}"] = value.to_s
138
+ end
139
+ end
140
+ end
141
+
131
142
  private
132
143
 
133
144
  def instrumented_integrations
@@ -139,19 +150,6 @@ module Datadog
139
150
 
140
151
  Datadog.configuration.tracing.instrumented_integrations
141
152
  end
142
-
143
- # Capture all active integration settings into "integrationName_settingName: value" entries.
144
- def instrumented_integrations_settings
145
- instrumented_integrations.flat_map do |name, integration|
146
- integration.configuration.to_h.flat_map do |setting, value|
147
- next [] if setting == :tracer # Skip internal Ruby objects
148
-
149
- # Convert value to a string to avoid custom #to_json
150
- # handlers possibly causing errors.
151
- [[:"integration_#{name}_#{setting}", value.to_s]]
152
- end
153
- end.to_h
154
- end
155
153
  end
156
154
  end
157
155
  end
@@ -3,6 +3,7 @@
3
3
  require_relative '../configuration/ext'
4
4
  require_relative '../trace_digest'
5
5
  require_relative '../trace_operation'
6
+ require_relative '../../core/telemetry/logger'
6
7
 
7
8
  module Datadog
8
9
  module Tracing
@@ -43,6 +44,7 @@ module Datadog
43
44
  # DEV-2.0: if needed.
44
45
  # DEV-2.0: Ideally, we'd have a separate stream to report tracer errors and never
45
46
  # DEV-2.0: touch the active span.
47
+ # DEV-3.0: Sample trace here instead of when generating digest.
46
48
  #
47
49
  # @param digest [TraceDigest]
48
50
  # @param data [Hash]
@@ -72,6 +74,10 @@ module Datadog
72
74
  ::Datadog.logger.error(
73
75
  "Error injecting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
74
76
  )
77
+ ::Datadog::Core::Telemetry::Logger.report(
78
+ e,
79
+ description: "Error injecting distributed trace data with #{propagator.class.name}"
80
+ )
75
81
  end
76
82
 
77
83
  result
@@ -127,6 +133,7 @@ module Datadog
127
133
  )
128
134
  end
129
135
  rescue => e
136
+ # TODO: Not to report Telemetry logs for now
130
137
  ::Datadog.logger.error(
131
138
  "Error extracting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
132
139
  )
@@ -10,8 +10,16 @@ module Datadog
10
10
  # Adds error tagging behavior
11
11
  # @public_api
12
12
  module Errors
13
- # Mark the span with the given error.
14
13
  def set_error(e)
14
+ Datadog::Core.log_deprecation do
15
+ 'Errors.set_error(..) is deprecated. ' \
16
+ 'Use Errors.set_error_tags(..) instead.'
17
+ end
18
+ set_error_tags(e)
19
+ end
20
+
21
+ # Mark the span with the given error.
22
+ def set_error_tags(e)
15
23
  e = Core::Error.build_from(e)
16
24
 
17
25
  set_tag(Ext::Errors::TAG_TYPE, e.type) unless e.type.empty?
@@ -14,6 +14,10 @@ module Datadog
14
14
  # Type of operation being performed (e.g. )
15
15
  TAG_OPERATION = 'operation'
16
16
  # Hostname of external service interacted with
17
+ #
18
+ # This tag also doesn't strictly need to be a “hostname”. It can be a raw IP address and in some cases it
19
+ # can even be a unix domain socket (i.e. postgres client setting host=/var/run/postgres).
20
+ # It should be whatever the client uses to point at the server it’s trying to talk to.
17
21
  TAG_PEER_HOSTNAME = 'peer.hostname'
18
22
  # Name of external service that performed the work
19
23
  TAG_PEER_SERVICE = 'peer.service'
@@ -83,6 +87,8 @@ module Datadog
83
87
  TAG_STATUS_CODE = 'http.status_code'
84
88
  TAG_USER_AGENT = 'http.useragent'
85
89
  TAG_URL = 'http.url'
90
+ TAG_ROUTE = 'http.route'
91
+ TAG_ROUTE_PATH = 'http.route.path'
86
92
  TYPE_INBOUND = AppTypes::TYPE_WEB.freeze
87
93
  TYPE_OUTBOUND = 'http'
88
94
  TYPE_PROXY = 'proxy'
@@ -10,8 +10,8 @@ module Datadog
10
10
  # This processor executes the configured `operation` for each {Datadog::Tracing::Span}
11
11
  # in a {Datadog::Tracing::TraceSegment}.
12
12
  #
13
- # If `operation` returns a truthy value for a span, that span is kept,
14
- # otherwise the span is removed from the trace.
13
+ # If `operation` returns a truthy value for a span, that span is dropped,
14
+ # otherwise the span is kept.
15
15
  #
16
16
  # @public_api
17
17
  class SpanFilter < SpanProcessor
@@ -13,7 +13,10 @@ module Datadog
13
13
  PRODUCT = 'APM_TRACING'
14
14
 
15
15
  CAPABILITIES = [
16
- 1 << 29 # APM_TRACING_SAMPLE_RULES: Dynamic trace sampling rules configuration
16
+ 1 << 12, # APM_TRACING_SAMPLE_RATE: Dynamic trace sampling rate configuration
17
+ 1 << 13, # APM_TRACING_LOGS_INJECTION: Dynamic trace logs injection configuration
18
+ 1 << 14, # APM_TRACING_HTTP_HEADER_TAGS: Dynamic trace HTTP header tags configuration
19
+ 1 << 29, # APM_TRACING_SAMPLE_RULES: Dynamic trace sampling rules configuration
17
20
  ].freeze
18
21
 
19
22
  def products
@@ -45,7 +48,7 @@ module Datadog
45
48
  content.errored("#{e.class.name} #{e.message}: #{Array(e.backtrace).join("\n")}")
46
49
  end
47
50
 
48
- def receivers
51
+ def receivers(_telemetry)
49
52
  receiver do |repository, _changes|
50
53
  # DEV: Filter our by product. Given it will be very common
51
54
  # DEV: we can filter this out before we receive the data in this method.
@@ -28,7 +28,7 @@ module Datadog
28
28
  # @return [#match?(String)]
29
29
  def self.glob_to_regex(glob)
30
30
  # Optimization for match-all case
31
- return MATCH_ALL if glob == MATCH_ALL_PATTERN
31
+ return MATCH_ALL if /\A\*+\z/.match?(glob)
32
32
 
33
33
  # Ensure no undesired characters are treated as regex.
34
34
  glob = Regexp.quote(glob)
@@ -100,6 +100,11 @@ module Datadog
100
100
  @tags.all? do |name, matcher|
101
101
  tag = trace.get_tag(name)
102
102
 
103
+ # Floats: Matching floating point values with a non-zero decimal part is not supported.
104
+ # For floating point values with a non-zero decimal part, any all * pattern always returns true.
105
+ # Other patterns always return false.
106
+ return false if tag.is_a?(Float) && tag.truncate != tag && matcher != MATCH_ALL
107
+
103
108
  # Format metrics as strings, to allow for partial number matching (/4.*/ matching '400', '404', etc.).
104
109
  # Because metrics are floats, we use the '%g' format specifier to avoid trailing zeros, which
105
110
  # can affect exact string matching (e.g. '400' matching '400.0').
@@ -20,7 +20,7 @@ module Datadog
20
20
  super()
21
21
 
22
22
  unless sample_rate >= 0.0 && sample_rate <= 1.0
23
- Datadog.logger.error('sample rate is not between 0 and 1, falling back to 1')
23
+ Datadog.logger.warn('sample rate is not between 0 and 1, falling back to 1')
24
24
  sample_rate = 1.0
25
25
  end
26
26
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'matcher'
4
4
  require_relative 'rate_sampler'
5
+ require_relative '../../core/telemetry/logger'
5
6
 
6
7
  module Datadog
7
8
  module Tracing
@@ -35,6 +36,7 @@ module Datadog
35
36
  Datadog.logger.error(
36
37
  "Matcher failed. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
37
38
  )
39
+ Datadog::Core::Telemetry::Logger.report(e, description: 'Matcher failed')
38
40
  nil
39
41
  end
40
42
 
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'ext'
4
- require_relative 'rate_limiter'
4
+ require_relative '../../core/rate_limiter'
5
5
  require_relative 'rule'
6
+ require_relative '../../core/telemetry/logger'
6
7
 
7
8
  module Datadog
8
9
  module Tracing
@@ -32,9 +33,9 @@ module Datadog
32
33
  @rate_limiter = if rate_limiter
33
34
  rate_limiter
34
35
  elsif rate_limit
35
- TokenBucket.new(rate_limit)
36
+ Core::TokenBucket.new(rate_limit)
36
37
  else
37
- UnlimitedLimiter.new
38
+ Core::UnlimitedLimiter.new
38
39
  end
39
40
 
40
41
  @default_sampler = if default_sampler
@@ -80,9 +81,10 @@ module Datadog
80
81
 
81
82
  new(parsed_rules, rate_limit: rate_limit, default_sample_rate: default_sample_rate)
82
83
  rescue => e
83
- Datadog.logger.error do
84
+ Datadog.logger.warn do
84
85
  "Could not parse trace sampling rules '#{rules}': #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
85
86
  end
87
+
86
88
  nil
87
89
  end
88
90
 
@@ -121,7 +123,7 @@ module Datadog
121
123
 
122
124
  return false unless sampled
123
125
 
124
- rate_limiter.allow?(1).tap do |allowed|
126
+ rate_limiter.allow?.tap do |allowed|
125
127
  set_priority(trace, allowed)
126
128
  set_limiter_metrics(trace, rate_limiter.effective_rate)
127
129
 
@@ -140,6 +142,8 @@ module Datadog
140
142
  Datadog.logger.error(
141
143
  "Rule sampling failed. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
142
144
  )
145
+ Datadog::Core::Telemetry::Logger.report(e, description: 'Rule sampling failed')
146
+
143
147
  yield(trace)
144
148
  end
145
149
 
@@ -9,7 +9,7 @@ module Datadog
9
9
  # Accept all spans (100% retention).
10
10
  DEFAULT_SAMPLE_RATE = 1.0
11
11
  # Unlimited.
12
- # @see Datadog::Tracing::Sampling::TokenBucket
12
+ # @see Datadog::Core::TokenBucket
13
13
  DEFAULT_MAX_PER_SECOND = -1
14
14
 
15
15
  # Sampling decision method used to come to the sampling decision for this span
@@ -30,7 +30,7 @@ module Datadog
30
30
  @rate_limit = rate_limit
31
31
 
32
32
  @sampler = Sampling::RateSampler.new(sample_rate)
33
- @rate_limiter = Sampling::TokenBucket.new(rate_limit)
33
+ @rate_limiter = Core::TokenBucket.new(rate_limit)
34
34
  end
35
35
 
36
36
  # This method should only be invoked for spans that are part
@@ -54,7 +54,7 @@ module Datadog
54
54
  def sample!(trace_op, span_op)
55
55
  return :not_matched unless @matcher.match?(span_op)
56
56
 
57
- if @rate_limiter.allow?(1) && @sampler.sample!(trace_op)
57
+ if @rate_limiter.allow? && @sampler.sample!(trace_op)
58
58
  span_op.set_metric(Span::Ext::TAG_MECHANISM, Sampling::Ext::Mechanism::SPAN_SAMPLING_RATE)
59
59
  span_op.set_metric(Span::Ext::TAG_RULE_RATE, @sample_rate)
60
60
  span_op.set_metric(Span::Ext::TAG_MAX_PER_SECOND, @rate_limit)
@@ -27,6 +27,7 @@ module Datadog
27
27
  :resource,
28
28
  :service,
29
29
  :links,
30
+ :events,
30
31
  :type,
31
32
  :start_time,
32
33
  :status,
@@ -45,6 +46,7 @@ module Datadog
45
46
  # * +parent_id+: the identifier of the parent span
46
47
  # * +trace_id+: the identifier of the root span for this trace
47
48
  # * +service_entry+: whether it is a service entry span.
49
+ # * +events+: the list of events that occurred while a span was active.
48
50
  def initialize(
49
51
  name,
50
52
  duration: nil,
@@ -60,7 +62,8 @@ module Datadog
60
62
  type: nil,
61
63
  trace_id: nil,
62
64
  service_entry: nil,
63
- links: nil
65
+ links: nil,
66
+ events: nil
64
67
  )
65
68
  @name = Core::Utils::SafeDup.frozen_or_dup(name)
66
69
  @service = Core::Utils::SafeDup.frozen_or_dup(service)
@@ -90,6 +93,8 @@ module Datadog
90
93
 
91
94
  @links = links || []
92
95
 
96
+ @events = events || []
97
+
93
98
  # Mark with the service entry span metric, if applicable
94
99
  set_metric(Metadata::Ext::TAG_TOP_LEVEL, 1.0) if service_entry
95
100
  end
@@ -112,7 +117,7 @@ module Datadog
112
117
 
113
118
  def set_error(e)
114
119
  @status = Metadata::Ext::Errors::STATUS
115
- super
120
+ set_error_tags(e)
116
121
  end
117
122
 
118
123
  # Spans with the same ID are considered the same span
@@ -149,6 +154,8 @@ module Datadog
149
154
  h[:duration] = duration_nano
150
155
  end
151
156
 
157
+ h[:meta]['events'] = @events.map(&:to_hash).to_json unless @events.empty?
158
+
152
159
  h
153
160
  end
154
161
 
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+
5
+ module Datadog
6
+ module Tracing
7
+ # Represents a timestamped annotation on a span. It is analogous to structured log message.
8
+ # @public_api
9
+ class SpanEvent
10
+ # @!attribute [r] name
11
+ # @return [Integer]
12
+ attr_reader :name
13
+
14
+ # @!attribute [r] attributes
15
+ # @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
16
+ attr_reader :attributes
17
+
18
+ # @!attribute [r] time_unix_nano
19
+ # @return [Integer]
20
+ attr_reader :time_unix_nano
21
+
22
+ def initialize(
23
+ name,
24
+ attributes: nil,
25
+ time_unix_nano: nil
26
+ )
27
+ @name = name
28
+ @attributes = attributes || {}
29
+ # OpenTelemetry SDK stores span event timestamps in nanoseconds (not seconds).
30
+ # We will do the same here to avoid unnecessary conversions and inconsistencies.
31
+ @time_unix_nano = time_unix_nano || (Time.now.to_r * 1_000_000_000).to_i
32
+ end
33
+
34
+ def to_hash
35
+ h = { name: @name, time_unix_nano: @time_unix_nano }
36
+ h[:attributes] = attributes unless @attributes.empty?
37
+ h
38
+ end
39
+ end
40
+ end
41
+ end