ddtrace 1.7.0 → 1.9.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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +100 -1
  3. data/README.md +2 -2
  4. data/ext/ddtrace_profiling_loader/extconf.rb +4 -1
  5. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +1 -1
  6. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +3 -2
  7. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +24 -50
  8. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +1 -1
  9. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +284 -74
  10. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.c +142 -0
  11. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.h +14 -0
  12. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.c +241 -0
  13. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.h +3 -0
  14. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +32 -32
  15. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +2 -2
  16. data/ext/ddtrace_profiling_native_extension/extconf.rb +21 -7
  17. data/ext/ddtrace_profiling_native_extension/helpers.h +5 -0
  18. data/ext/ddtrace_profiling_native_extension/http_transport.c +50 -49
  19. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +5 -1
  20. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +42 -12
  21. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +116 -22
  22. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +9 -0
  23. data/ext/ddtrace_profiling_native_extension/profiling.c +205 -0
  24. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +86 -0
  25. data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +28 -6
  26. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.c +23 -4
  27. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.h +4 -0
  28. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +47 -50
  29. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +4 -4
  30. data/ext/ddtrace_profiling_native_extension/time_helpers.c +17 -0
  31. data/ext/ddtrace_profiling_native_extension/time_helpers.h +10 -0
  32. data/lib/datadog/appsec/assets/waf_rules/recommended.json +75 -8
  33. data/lib/datadog/appsec/assets/waf_rules/risky.json +1 -1
  34. data/lib/datadog/appsec/assets/waf_rules/strict.json +1 -1
  35. data/lib/datadog/appsec/assets.rb +1 -1
  36. data/lib/datadog/appsec/configuration/settings.rb +35 -22
  37. data/lib/datadog/appsec/configuration.rb +4 -2
  38. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  39. data/lib/datadog/appsec/contrib/configuration/settings.rb +1 -1
  40. data/lib/datadog/appsec/contrib/integration.rb +1 -1
  41. data/lib/datadog/appsec/contrib/patcher.rb +1 -1
  42. data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +1 -1
  43. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  44. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +1 -1
  45. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +1 -1
  46. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +1 -1
  47. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +1 -1
  48. data/lib/datadog/appsec/contrib/rack/request.rb +1 -1
  49. data/lib/datadog/appsec/contrib/rack/response.rb +1 -1
  50. data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +1 -1
  51. data/lib/datadog/appsec/contrib/rails/ext.rb +1 -1
  52. data/lib/datadog/appsec/contrib/rails/framework.rb +1 -1
  53. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +1 -1
  54. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +1 -1
  55. data/lib/datadog/appsec/contrib/rails/request.rb +1 -1
  56. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +1 -1
  57. data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +1 -1
  58. data/lib/datadog/appsec/contrib/sinatra/ext.rb +1 -1
  59. data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -1
  60. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +1 -1
  61. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +1 -1
  62. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +1 -1
  63. data/lib/datadog/appsec/event.rb +1 -1
  64. data/lib/datadog/appsec/extensions.rb +36 -26
  65. data/lib/datadog/appsec/instrumentation/gateway.rb +3 -3
  66. data/lib/datadog/appsec/processor.rb +15 -19
  67. data/lib/datadog/appsec/rate_limiter.rb +1 -1
  68. data/lib/datadog/appsec/reactive/address_hash.rb +1 -1
  69. data/lib/datadog/appsec/reactive/engine.rb +1 -1
  70. data/lib/datadog/appsec/reactive/operation.rb +2 -2
  71. data/lib/datadog/appsec/reactive/subscriber.rb +1 -1
  72. data/lib/datadog/appsec/response.rb +18 -9
  73. data/lib/datadog/appsec/utils/http/media_range.rb +201 -0
  74. data/lib/datadog/appsec/utils/http/media_type.rb +87 -0
  75. data/lib/datadog/appsec/utils/http.rb +9 -0
  76. data/lib/datadog/appsec/utils.rb +7 -0
  77. data/lib/datadog/appsec.rb +1 -1
  78. data/lib/datadog/ci/ext/environment.rb +57 -13
  79. data/lib/datadog/core/configuration/agent_settings_resolver.rb +2 -2
  80. data/lib/datadog/core/configuration/base.rb +3 -0
  81. data/lib/datadog/core/configuration/components.rb +27 -6
  82. data/lib/datadog/core/configuration/ext.rb +26 -0
  83. data/lib/datadog/core/configuration/option_definition.rb +11 -2
  84. data/lib/datadog/core/configuration/settings.rb +16 -341
  85. data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
  86. data/lib/datadog/core/diagnostics/health.rb +4 -22
  87. data/lib/datadog/core/environment/variable_helpers.rb +58 -10
  88. data/lib/datadog/core/metrics/client.rb +3 -2
  89. data/lib/datadog/core/metrics/ext.rb +0 -2
  90. data/lib/datadog/core/telemetry/collector.rb +1 -0
  91. data/lib/datadog/core/utils.rb +0 -21
  92. data/lib/datadog/core.rb +21 -1
  93. data/lib/datadog/kit/appsec/events.rb +75 -0
  94. data/lib/datadog/kit/enable_core_dumps.rb +1 -0
  95. data/lib/datadog/kit/identity.rb +8 -7
  96. data/lib/datadog/opentelemetry/api/context.rb +187 -0
  97. data/lib/datadog/opentelemetry/api/trace/span.rb +15 -0
  98. data/lib/datadog/opentelemetry/sdk/configurator.rb +38 -0
  99. data/lib/datadog/opentelemetry/sdk/id_generator.rb +27 -0
  100. data/lib/datadog/opentelemetry/sdk/propagator.rb +91 -0
  101. data/lib/datadog/opentelemetry/sdk/span_processor.rb +92 -0
  102. data/lib/datadog/opentelemetry.rb +48 -0
  103. data/lib/datadog/opentracer/distributed_headers.rb +2 -2
  104. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +16 -5
  105. data/lib/datadog/profiling/collectors/dynamic_sampling_rate.rb +14 -0
  106. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +68 -0
  107. data/lib/datadog/profiling/stack_recorder.rb +14 -0
  108. data/lib/datadog/profiling.rb +2 -0
  109. data/lib/datadog/tracing/configuration/ext.rb +33 -4
  110. data/lib/datadog/tracing/configuration/settings.rb +433 -0
  111. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +4 -1
  112. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  113. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +4 -1
  114. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  115. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +5 -1
  116. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
  117. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +6 -1
  118. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  119. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +5 -1
  120. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  121. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +5 -1
  122. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  123. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +6 -1
  124. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +9 -4
  125. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  126. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -1
  127. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +10 -3
  128. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +9 -4
  129. data/lib/datadog/tracing/contrib/http/ext.rb +2 -0
  130. data/lib/datadog/tracing/contrib/http/instrumentation.rb +3 -6
  131. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -1
  132. data/lib/datadog/tracing/contrib/httpclient/ext.rb +2 -0
  133. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +3 -4
  134. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -1
  135. data/lib/datadog/tracing/contrib/httprb/ext.rb +2 -0
  136. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +3 -4
  137. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +5 -1
  138. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  139. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +4 -1
  140. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  141. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -2
  142. data/lib/datadog/tracing/contrib/patcher.rb +3 -2
  143. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +4 -1
  144. data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
  145. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +56 -33
  146. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +4 -1
  147. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  148. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +1 -0
  149. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +10 -12
  150. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +4 -1
  151. data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
  152. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +30 -23
  153. data/lib/datadog/tracing/contrib/redis/integration.rb +34 -2
  154. data/lib/datadog/tracing/contrib/redis/patcher.rb +18 -14
  155. data/lib/datadog/tracing/contrib/redis/quantize.rb +12 -9
  156. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -6
  157. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +72 -0
  158. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +6 -1
  159. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  160. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +33 -0
  161. data/lib/datadog/tracing/contrib/stripe/ext.rb +26 -0
  162. data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
  163. data/lib/datadog/tracing/contrib/stripe/patcher.rb +29 -0
  164. data/lib/datadog/tracing/contrib/stripe/request.rb +67 -0
  165. data/lib/datadog/tracing/contrib.rb +1 -0
  166. data/lib/datadog/{core → tracing}/diagnostics/ext.rb +1 -6
  167. data/lib/datadog/tracing/diagnostics/health.rb +40 -0
  168. data/lib/datadog/tracing/distributed/{b3.rb → b3_multi.rb} +2 -2
  169. data/lib/datadog/tracing/distributed/helpers.rb +2 -1
  170. data/lib/datadog/tracing/distributed/none.rb +19 -0
  171. data/lib/datadog/tracing/distributed/trace_context.rb +378 -0
  172. data/lib/datadog/tracing/metadata/ext.rb +1 -1
  173. data/lib/datadog/tracing/metadata/tagging.rb +6 -0
  174. data/lib/datadog/tracing/sampling/priority_sampler.rb +11 -0
  175. data/lib/datadog/tracing/sampling/rate_sampler.rb +3 -3
  176. data/lib/datadog/tracing/span.rb +3 -19
  177. data/lib/datadog/tracing/span_operation.rb +5 -4
  178. data/lib/datadog/tracing/trace_digest.rb +85 -2
  179. data/lib/datadog/tracing/trace_operation.rb +13 -4
  180. data/lib/datadog/tracing/utils.rb +50 -0
  181. data/lib/ddtrace/version.rb +1 -1
  182. metadata +41 -9
@@ -20,67 +20,75 @@ module Datadog
20
20
 
21
21
  # PG::Connection patch methods
22
22
  module InstanceMethods
23
- def exec(sql, *args)
24
- trace(Ext::SPAN_EXEC, sql: sql) do |sql_statement|
25
- super(sql_statement, *args)
23
+ def exec(sql, *args, &block)
24
+ trace(Ext::SPAN_EXEC, sql: sql, block: block) do |sql_statement, wrapped_block|
25
+ super(sql_statement, *args, &wrapped_block)
26
26
  end
27
27
  end
28
28
 
29
- def exec_params(sql, params, *args)
30
- trace(Ext::SPAN_EXEC_PARAMS, sql: sql) do |sql_statement|
31
- super(sql_statement, params, *args)
29
+ def exec_params(sql, params, *args, &block)
30
+ trace(Ext::SPAN_EXEC_PARAMS, sql: sql, block: block) do |sql_statement, wrapped_block|
31
+ super(sql_statement, params, *args, &wrapped_block)
32
32
  end
33
33
  end
34
34
 
35
- def exec_prepared(statement_name, params, *args)
36
- trace(Ext::SPAN_EXEC_PREPARED, statement_name: statement_name) do
37
- super(statement_name, params, *args)
35
+ def exec_prepared(statement_name, params, *args, &block)
36
+ trace(Ext::SPAN_EXEC_PREPARED, statement_name: statement_name, block: block) do |_, wrapped_block|
37
+ super(statement_name, params, *args, &wrapped_block)
38
38
  end
39
39
  end
40
40
 
41
- def async_exec(sql, *args)
42
- trace(Ext::SPAN_ASYNC_EXEC, sql: sql) do |sql_statement|
43
- super(sql_statement, *args)
41
+ # async_exec is an alias to exec
42
+ def async_exec(sql, *args, &block)
43
+ trace(Ext::SPAN_ASYNC_EXEC, sql: sql, block: block) do |sql_statement, wrapped_block|
44
+ super(sql_statement, *args, &wrapped_block)
44
45
  end
45
46
  end
46
47
 
47
- def async_exec_params(sql, params, *args)
48
- trace(Ext::SPAN_ASYNC_EXEC_PARAMS, sql: sql) do |sql_statement|
49
- super(sql_statement, params, *args)
48
+ # async_exec_params is an alias to exec_params
49
+ def async_exec_params(sql, params, *args, &block)
50
+ trace(Ext::SPAN_ASYNC_EXEC_PARAMS, sql: sql, block: block) do |sql_statement, wrapped_block|
51
+ super(sql_statement, params, *args, &wrapped_block)
50
52
  end
51
53
  end
52
54
 
53
- def async_exec_prepared(statement_name, params, *args)
54
- trace(Ext::SPAN_ASYNC_EXEC_PREPARED, statement_name: statement_name) do
55
- super(statement_name, params, *args)
55
+ # async_exec_prepared is an alias to exec_prepared
56
+ def async_exec_prepared(statement_name, params, *args, &block)
57
+ trace(Ext::SPAN_ASYNC_EXEC_PREPARED, statement_name: statement_name, block: block) do |_, wrapped_block|
58
+ super(statement_name, params, *args, &wrapped_block)
56
59
  end
57
60
  end
58
61
 
59
- def sync_exec(sql, *args)
60
- trace(Ext::SPAN_SYNC_EXEC, sql: sql) do |sql_statement|
61
- super(sql_statement, *args)
62
+ def sync_exec(sql, *args, &block)
63
+ trace(Ext::SPAN_SYNC_EXEC, sql: sql, block: block) do |sql_statement, wrapped_block|
64
+ super(sql_statement, *args, &wrapped_block)
62
65
  end
63
66
  end
64
67
 
65
- def sync_exec_params(sql, params, *args)
66
- trace(Ext::SPAN_SYNC_EXEC_PARAMS, sql: sql) do |sql_statement|
67
- super(sql_statement, params, *args)
68
+ def sync_exec_params(sql, params, *args, &block)
69
+ trace(Ext::SPAN_SYNC_EXEC_PARAMS, sql: sql, block: block) do |sql_statement, wrapped_block|
70
+ super(sql_statement, params, *args, &wrapped_block)
68
71
  end
69
72
  end
70
73
 
71
- def sync_exec_prepared(statement_name, params, *args)
72
- trace(Ext::SPAN_SYNC_EXEC_PREPARED, statement_name: statement_name) do
73
- super(statement_name, params, *args)
74
+ def sync_exec_prepared(statement_name, params, *args, &block)
75
+ trace(Ext::SPAN_SYNC_EXEC_PREPARED, statement_name: statement_name, block: block) do |_, wrapped_block|
76
+ super(statement_name, params, *args, &wrapped_block)
74
77
  end
75
78
  end
76
79
 
77
80
  private
78
81
 
79
- def trace(name, sql: nil, statement_name: nil)
82
+ def trace(name, sql: nil, statement_name: nil, block: nil)
80
83
  service = Datadog.configuration_for(self, :service_name) || datadog_configuration[:service_name]
81
84
  resource = statement_name || sql
82
85
 
83
- Tracing.trace(name, service: service, resource: resource, type: Tracing::Metadata::Ext::SQL::TYPE) do |span|
86
+ Tracing.trace(
87
+ name,
88
+ service: service,
89
+ resource: resource,
90
+ type: Tracing::Metadata::Ext::SQL::TYPE
91
+ ) do |span, trace_op|
84
92
  annotate_span_with_query!(span, service)
85
93
  # Set analytics sample rate
86
94
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
@@ -88,12 +96,26 @@ module Datadog
88
96
  if sql
89
97
  propagation_mode = Contrib::Propagation::SqlComment::Mode.new(comment_propagation)
90
98
  Contrib::Propagation::SqlComment.annotate!(span, propagation_mode)
91
- propagated_sql_statement = Contrib::Propagation::SqlComment.prepend_comment(sql, span, propagation_mode)
99
+ propagated_sql_statement = Contrib::Propagation::SqlComment.prepend_comment(
100
+ sql,
101
+ span,
102
+ trace_op,
103
+ propagation_mode
104
+ )
92
105
  end
93
106
 
94
- result = yield(propagated_sql_statement)
95
- annotate_span_with_result!(span, result)
96
- result
107
+ # Read metadata from PG::Result
108
+ if block
109
+ yield(propagated_sql_statement, proc do |result|
110
+ ret = block.call(result)
111
+ annotate_span_with_result!(span, result)
112
+ ret
113
+ end)
114
+ else
115
+ result = yield(propagated_sql_statement)
116
+ annotate_span_with_result!(span, result)
117
+ result
118
+ end
97
119
  end
98
120
  end
99
121
 
@@ -118,6 +140,7 @@ module Datadog
118
140
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_DESTINATION_PORT, port)
119
141
  end
120
142
 
143
+ # @param [PG::Result] result
121
144
  def annotate_span_with_result!(span, result)
122
145
  span.set_tag(Contrib::Ext::DB::TAG_ROW_COUNT, result.ntuples)
123
146
  end
@@ -26,7 +26,10 @@ module Datadog
26
26
  o.lazy
27
27
  end
28
28
 
29
- option :service_name, default: Ext::DEFAULT_PEER_SERVICE_NAME
29
+ option :service_name do |o|
30
+ o.default { ENV.fetch(Ext::ENV_SERVICE_NAME, Ext::DEFAULT_PEER_SERVICE_NAME) }
31
+ o.lazy
32
+ end
30
33
  end
31
34
  end
32
35
  end
@@ -8,6 +8,7 @@ module Datadog
8
8
  # @public_api Changing resource names, tag names, or environment variables creates breaking changes.
9
9
  module Ext
10
10
  ENV_ENABLED = 'DD_TRACE_PRESTO_ENABLED'.freeze
11
+ ENV_SERVICE_NAME = 'DD_TRACE_PRESTO_SERVICE_NAME'.freeze
11
12
  ENV_ANALYTICS_ENABLED = 'DD_TRACE_PRESTO_ANALYTICS_ENABLED'.freeze
12
13
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_PRESTO_ANALYTICS_SAMPLE_RATE'.freeze
13
14
  DEFAULT_PEER_SERVICE_NAME = 'presto'.freeze
@@ -24,6 +24,7 @@ module Datadog
24
24
  KEY_ENVIRONMENT = 'dde'.freeze
25
25
  KEY_PARENT_SERVICE = 'ddps'.freeze
26
26
  KEY_VERSION = 'ddpv'.freeze
27
+ KEY_TRACEPARENT = 'traceparent'.freeze
27
28
  end
28
29
  end
29
30
  end
@@ -3,6 +3,8 @@
3
3
  require_relative 'sql_comment/comment'
4
4
  require_relative 'sql_comment/ext'
5
5
 
6
+ require_relative '../../distributed/trace_context'
7
+
6
8
  module Datadog
7
9
  module Tracing
8
10
  module Contrib
@@ -12,11 +14,12 @@ module Datadog
12
14
  def self.annotate!(span_op, mode)
13
15
  return unless mode.enabled?
14
16
 
15
- # PENDING: Until `traceparent`` implementation in `full` mode
16
- # span_op.set_tag(Ext::TAG_DBM_TRACE_INJECTED, true) if mode.full?
17
+ span_op.set_tag(Ext::TAG_DBM_TRACE_INJECTED, true) if mode.full?
17
18
  end
18
19
 
19
- def self.prepend_comment(sql, span_op, mode)
20
+ # Inject span_op and trace_op instead of TraceDigest to improve memory usage
21
+ # for `disabled` and `service` mode
22
+ def self.prepend_comment(sql, span_op, trace_op, mode)
20
23
  return sql unless mode.enabled?
21
24
 
22
25
  tags = {
@@ -26,8 +29,10 @@ module Datadog
26
29
  Ext::KEY_VERSION => datadog_configuration.version
27
30
  }
28
31
 
29
- # PENDING: Until `traceparent`` implementation in `full` mode
30
- # tags.merge!(trace_context(span_op)) if mode.full?
32
+ if mode.full?
33
+ tags[Ext::KEY_TRACEPARENT] =
34
+ Tracing::Distributed::TraceContext.new(fetcher: nil).send(:build_traceparent, trace_op.to_digest)
35
+ end
31
36
 
32
37
  "#{Comment.new(tags)} #{sql}"
33
38
  end
@@ -35,13 +40,6 @@ module Datadog
35
40
  def self.datadog_configuration
36
41
  Datadog.configuration
37
42
  end
38
-
39
- # TODO: Derive from trace
40
- def self.trace_context(_)
41
- {
42
- # traceparent: '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01'
43
- }.freeze
44
- end
45
43
  end
46
44
  end
47
45
  end
@@ -31,7 +31,10 @@ module Datadog
31
31
  o.lazy
32
32
  end
33
33
 
34
- option :service_name, default: Ext::DEFAULT_PEER_SERVICE_NAME
34
+ option :service_name do |o|
35
+ o.default { ENV.fetch(Ext::ENV_SERVICE_NAME, Ext::DEFAULT_PEER_SERVICE_NAME) }
36
+ o.lazy
37
+ end
35
38
  end
36
39
  end
37
40
  end
@@ -8,6 +8,7 @@ module Datadog
8
8
  # @public_api Changing resource names, tag names, or environment variables creates breaking changes.
9
9
  module Ext
10
10
  ENV_ENABLED = 'DD_TRACE_REDIS_ENABLED'.freeze
11
+ ENV_SERVICE_NAME = 'DD_TRACE_REDIS_SERVICE_NAME'.freeze
11
12
  ENV_ANALYTICS_ENABLED = 'DD_TRACE_REDIS_ANALYTICS_ENABLED'.freeze
12
13
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_REDIS_ANALYTICS_SAMPLE_RATE'.freeze
13
14
  ENV_COMMAND_ARGS = 'DD_REDIS_COMMAND_ARGS'.freeze
@@ -10,7 +10,7 @@ module Datadog
10
10
  module Tracing
11
11
  module Contrib
12
12
  module Redis
13
- # Instrumentation for Redis
13
+ # Instrumentation for Redis < 5
14
14
  module Instrumentation
15
15
  def self.included(base)
16
16
  base.prepend(InstanceMethods)
@@ -19,51 +19,58 @@ module Datadog
19
19
  # InstanceMethods - implementing instrumentation
20
20
  module InstanceMethods
21
21
  def call(*args, &block)
22
- response = nil
22
+ show_command_args = command_args?
23
+
23
24
  Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
24
- span.service = Datadog.configuration_for(redis_instance, :service_name) ||
25
- datadog_configuration[:service_name]
25
+ span.service = service_name
26
26
  span.span_type = Contrib::Redis::Ext::TYPE
27
- span.resource = get_command(args)
28
- Contrib::Redis::Tags.set_common_tags(self, span)
29
- span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
27
+ span.resource = get_command(args, show_command_args)
28
+ Contrib::Redis::Tags.set_common_tags(self, span, show_command_args)
30
29
 
31
- response = super
30
+ super
32
31
  end
33
-
34
- response
35
32
  end
36
33
 
37
34
  def call_pipeline(*args, &block)
38
- response = nil
35
+ show_command_args = command_args?
36
+
39
37
  Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
40
- span.service = Datadog.configuration_for(redis_instance, :service_name) ||
41
- datadog_configuration[:service_name]
38
+ span.service = service_name
42
39
  span.span_type = Contrib::Redis::Ext::TYPE
43
- commands = get_pipeline_commands(args)
40
+ commands = get_pipeline_commands(args, show_command_args)
44
41
  span.resource = commands.any? ? commands.join("\n") : '(none)'
45
42
  span.set_metric Contrib::Redis::Ext::METRIC_PIPELINE_LEN, commands.length
46
- Contrib::Redis::Tags.set_common_tags(self, span)
47
- span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
43
+ Contrib::Redis::Tags.set_common_tags(self, span, show_command_args)
48
44
 
49
- response = super
45
+ super
50
46
  end
51
-
52
- response
53
47
  end
54
48
 
55
49
  private
56
50
 
57
- def get_command(args)
58
- if datadog_configuration[:command_args]
51
+ def command_args?
52
+ pinned = Datadog.configuration_for(redis_instance, :command_args)
53
+
54
+ return pinned unless pinned.nil?
55
+
56
+ datadog_configuration[:command_args]
57
+ end
58
+
59
+ def service_name
60
+ Datadog.configuration_for(redis_instance, :service_name) ||
61
+ datadog_configuration[:service_name]
62
+ end
63
+
64
+ def get_command(args, show_command_args)
65
+ if show_command_args
59
66
  Contrib::Redis::Quantize.format_command_args(*args)
60
67
  else
61
68
  Contrib::Redis::Quantize.get_verb(*args)
62
69
  end
63
70
  end
64
71
 
65
- def get_pipeline_commands(args)
66
- if datadog_configuration[:command_args]
72
+ def get_pipeline_commands(args, show_command_args)
73
+ if show_command_args
67
74
  args[0].commands.map { |c| Contrib::Redis::Quantize.format_command_args(c) }
68
75
  else
69
76
  args[0].commands.map { |c| Contrib::Redis::Quantize.get_verb(c) }
@@ -13,21 +13,53 @@ module Datadog
13
13
  include Contrib::Integration
14
14
 
15
15
  MINIMUM_VERSION = Gem::Version.new('3.2')
16
- MAX_VERSION = Gem::Version.new('5')
16
+
17
+ # Support `Config#custom`
18
+ # https://github.com/redis-rb/redis-client/blob/master/CHANGELOG.md#0110
19
+ REDISCLIENT_MINIMUM_VERSION = Gem::Version.new('0.11.0')
17
20
 
18
21
  # @public_api Changing the integration name or integration options can cause breaking changes
19
22
  register_as :redis, auto_patch: true
20
23
 
24
+ # Until Redis 4, all instrumentation happened in one gem: redis.
25
+ # Since Redis 5, instrumentation happens in a separate gem: redis-client.
26
+ # Because Redis 4 does not depend on redis-client, it's possible for both gems to be installed at the same time.
27
+ # For example, if Sidekiq 7 and Redis 4 are installed: both redis and redis-client will be installed.
28
+ # If redis-client and redis > 5 are installed, than they will be in sync, and only redis-client will be installed.
21
29
  def self.version
30
+ redis_version || redis_client_version
31
+ end
32
+
33
+ def self.redis_version
22
34
  Gem.loaded_specs['redis'] && Gem.loaded_specs['redis'].version
23
35
  end
24
36
 
37
+ def self.redis_client_version
38
+ Gem.loaded_specs['redis-client'] && Gem.loaded_specs['redis-client'].version
39
+ end
40
+
25
41
  def self.loaded?
42
+ redis_loaded? || redis_client_loaded?
43
+ end
44
+
45
+ def self.redis_loaded?
26
46
  !defined?(::Redis).nil?
27
47
  end
28
48
 
49
+ def self.redis_client_loaded?
50
+ !defined?(::RedisClient).nil?
51
+ end
52
+
29
53
  def self.compatible?
30
- super && version >= MINIMUM_VERSION && version < MAX_VERSION
54
+ super && (redis_compatible? || redis_client_compatible?)
55
+ end
56
+
57
+ def self.redis_compatible?
58
+ !!(redis_version && redis_version >= MINIMUM_VERSION)
59
+ end
60
+
61
+ def self.redis_client_compatible?
62
+ !!(redis_client_version && redis_client_version >= REDISCLIENT_MINIMUM_VERSION)
31
63
  end
32
64
 
33
65
  def new_configuration
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: ignore
2
2
 
3
3
  require_relative '../patcher'
4
4
  require_relative 'ext'
@@ -49,24 +49,28 @@ module Datadog
49
49
 
50
50
  module_function
51
51
 
52
- def target_version
53
- Integration.version
52
+ def default_tags
53
+ [].tap do |tags|
54
+ tags << "target_redis_version:#{Integration.redis_version}" if Integration.redis_version
55
+ tags << "target_redis_client_version:#{Integration.redis_client_version}" if Integration.redis_client_version
56
+ end
54
57
  end
55
58
 
56
- # patch applies our patch if needed
57
59
  def patch
58
- # do not require these by default, but only when actually patching
59
- require 'redis'
60
- require_relative 'tags'
61
- require_relative 'quantize'
62
- require_relative 'instrumentation'
60
+ # Redis 5+ extracts RedisClient to its own gem and provide instrumentation interface
61
+ if Integration.redis_client_compatible?
62
+ require_relative 'trace_middleware'
63
+
64
+ ::RedisClient.register(TraceMiddleware)
65
+ end
63
66
 
64
- # InstancePatch and ClientPatch allows the client object to access pin on redis instance
65
- ::Redis.include(InstancePatch)
66
- ::Redis::Client.include(ClientPatch)
67
+ if Integration.redis_compatible? && Integration.redis_version < Gem::Version.new('5.0.0')
68
+ require_relative 'instrumentation'
67
69
 
68
- # TODO: To support redis-rb 5.x, Redis::Client -> RedisClient
69
- ::Redis::Client.include(Instrumentation)
70
+ ::Redis.include(InstancePatch)
71
+ ::Redis::Client.include(ClientPatch)
72
+ ::Redis::Client.include(Instrumentation)
73
+ end
70
74
  end
71
75
  end
72
76
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # typed: true
2
4
 
3
5
  require 'set'
@@ -8,11 +10,13 @@ module Datadog
8
10
  module Redis
9
11
  # Quantize contains Redis-specific resource quantization tools.
10
12
  module Quantize
11
- PLACEHOLDER = '?'.freeze
12
- TOO_LONG_MARK = '...'.freeze
13
+ PLACEHOLDER = '?'
14
+ TOO_LONG_MARK = '...'
13
15
  VALUE_MAX_LEN = 50
14
16
  CMD_MAX_LEN = 500
15
17
 
18
+ AUTH_COMMANDS = %w[AUTH auth].freeze
19
+
16
20
  MULTI_VERB_COMMANDS = Set.new(
17
21
  %w[
18
22
  ACL
@@ -29,8 +33,7 @@ module Datadog
29
33
  module_function
30
34
 
31
35
  def format_arg(arg)
32
- str = arg.is_a?(Symbol) ? arg.to_s.upcase : arg.to_s
33
- str = Core::Utils.utf8_encode(str, binary: true, placeholder: PLACEHOLDER)
36
+ str = Core::Utils.utf8_encode(arg, binary: true, placeholder: PLACEHOLDER)
34
37
  Core::Utils.truncate(str, VALUE_MAX_LEN, TOO_LONG_MARK)
35
38
  rescue => e
36
39
  Datadog.logger.debug("non formattable Redis arg #{str}: #{e}")
@@ -41,8 +44,8 @@ module Datadog
41
44
  command_args = resolve_command_args(command_args)
42
45
  return 'AUTH ?' if auth_command?(command_args)
43
46
 
44
- cmd = command_args.map { |x| format_arg(x) }.join(' ')
45
- Core::Utils.truncate(cmd, CMD_MAX_LEN, TOO_LONG_MARK)
47
+ verb, *args = command_args.map { |x| format_arg(x) }
48
+ Core::Utils.truncate("#{verb.upcase} #{args.join(' ')}", CMD_MAX_LEN, TOO_LONG_MARK)
46
49
  end
47
50
 
48
51
  def get_verb(command_args)
@@ -50,8 +53,7 @@ module Datadog
50
53
 
51
54
  return get_verb(command_args.first) if command_args.first.is_a?(Array)
52
55
 
53
- arg = command_args.first
54
- verb = arg.is_a?(Symbol) ? arg.to_s.upcase : arg.to_s
56
+ verb = command_args.first.to_s.upcase
55
57
  return verb unless MULTI_VERB_COMMANDS.include?(verb) && command_args[1]
56
58
 
57
59
  "#{verb} #{command_args[1]}"
@@ -60,7 +62,8 @@ module Datadog
60
62
  def auth_command?(command_args)
61
63
  return false unless command_args.is_a?(Array) && !command_args.empty?
62
64
 
63
- command_args.first.to_sym == :auth
65
+ verb = command_args.first.to_s
66
+ AUTH_COMMANDS.include?(verb)
64
67
  end
65
68
 
66
69
  # Unwraps command array when Redis is called with the following syntax:
@@ -12,7 +12,7 @@ module Datadog
12
12
  # Tags handles generic common tags assignment.
13
13
  module Tags
14
14
  class << self
15
- def set_common_tags(client, span)
15
+ def set_common_tags(client, span, show_command_args)
16
16
  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
17
17
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_COMMAND)
18
18
 
@@ -20,6 +20,8 @@ module Datadog
20
20
  span.set_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE, span.service)
21
21
  span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, client.host)
22
22
 
23
+ span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)
24
+
23
25
  # Set analytics sample rate
24
26
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
25
27
 
@@ -30,7 +32,7 @@ module Datadog
30
32
 
31
33
  span.set_tag Ext::TAG_DATABASE_INDEX, client.db.to_s
32
34
  span.set_tag Ext::TAG_DB, client.db
33
- span.set_tag Ext::TAG_RAW_COMMAND, span.resource if show_command_args?
35
+ span.set_tag Ext::TAG_RAW_COMMAND, span.resource if show_command_args
34
36
  end
35
37
 
36
38
  private
@@ -46,10 +48,6 @@ module Datadog
46
48
  def analytics_sample_rate
47
49
  datadog_configuration[:analytics_sample_rate]
48
50
  end
49
-
50
- def show_command_args?
51
- datadog_configuration[:command_args]
52
- end
53
51
  end
54
52
  end
55
53
  end
@@ -0,0 +1,72 @@
1
+ # typed: false
2
+
3
+ require_relative '../patcher'
4
+ require_relative 'ext'
5
+ require_relative 'quantize'
6
+ require_relative 'tags'
7
+
8
+ module Datadog
9
+ module Tracing
10
+ module Contrib
11
+ module Redis
12
+ # Instrumentation for Redis 5+
13
+ module TraceMiddleware
14
+ def call(commands, redis_config)
15
+ Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
16
+ datadog_configuration = resolve(redis_config)
17
+ resource = get_command(commands, datadog_configuration[:command_args])
18
+
19
+ span.service = datadog_configuration[:service_name]
20
+ span.span_type = Contrib::Redis::Ext::TYPE
21
+ span.resource = resource
22
+
23
+ Contrib::Redis::Tags.set_common_tags(redis_config, span, datadog_configuration[:command_args])
24
+
25
+ super
26
+ end
27
+ end
28
+
29
+ def call_pipelined(commands, redis_config)
30
+ Tracing.trace(Contrib::Redis::Ext::SPAN_COMMAND) do |span|
31
+ datadog_configuration = resolve(redis_config)
32
+ pipelined_commands = get_pipeline_commands(commands, datadog_configuration[:command_args])
33
+
34
+ span.service = datadog_configuration[:service_name]
35
+ span.span_type = Contrib::Redis::Ext::TYPE
36
+ span.resource = pipelined_commands.join("\n")
37
+ span.set_metric Contrib::Redis::Ext::METRIC_PIPELINE_LEN, pipelined_commands.length
38
+
39
+ Contrib::Redis::Tags.set_common_tags(redis_config, span, datadog_configuration[:command_args])
40
+
41
+ super
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def get_command(commands, boolean)
48
+ if boolean
49
+ Contrib::Redis::Quantize.format_command_args(commands)
50
+ else
51
+ Contrib::Redis::Quantize.get_verb(commands)
52
+ end
53
+ end
54
+
55
+ def get_pipeline_commands(commands, boolean)
56
+ if boolean
57
+ commands.map { |c| Contrib::Redis::Quantize.format_command_args(c) }
58
+ else
59
+ commands.map { |c| Contrib::Redis::Quantize.get_verb(c) }
60
+ end
61
+ end
62
+
63
+ def resolve(redis_config)
64
+ custom = redis_config.custom[:datadog] || {}
65
+
66
+ Datadog.configuration.tracing[:redis, redis_config.server_url].to_h.merge(custom)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -27,7 +27,12 @@ module Datadog
27
27
  end
28
28
 
29
29
  option :distributed_tracing, default: true
30
- option :service_name, default: Ext::DEFAULT_PEER_SERVICE_NAME
30
+
31
+ option :service_name do |o|
32
+ o.default { ENV.fetch(Ext::ENV_SERVICE_NAME, Ext::DEFAULT_PEER_SERVICE_NAME) }
33
+ o.lazy
34
+ end
35
+
31
36
  option :split_by_domain, default: false
32
37
  end
33
38
  end
@@ -8,6 +8,7 @@ module Datadog
8
8
  # @public_api Changing resource names, tag names, or environment variables creates breaking changes.
9
9
  module Ext
10
10
  ENV_ENABLED = 'DD_TRACE_REST_CLIENT_ENABLED'.freeze
11
+ ENV_SERVICE_NAME = 'DD_TRACE_REST_CLIENT_SERVICE_NAME'.freeze
11
12
  ENV_ANALYTICS_ENABLED = 'DD_TRACE_REST_CLIENT_ANALYTICS_ENABLED'.freeze
12
13
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_REST_CLIENT_ANALYTICS_SAMPLE_RATE'.freeze
13
14
  DEFAULT_PEER_SERVICE_NAME = 'rest_client'.freeze