ddtrace 1.8.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +10 -10
  4. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +32 -32
  5. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +2 -2
  6. data/ext/ddtrace_profiling_native_extension/http_transport.c +50 -49
  7. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +5 -1
  8. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +34 -12
  9. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +10 -0
  10. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +32 -32
  11. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +4 -4
  12. data/lib/datadog/appsec/assets/waf_rules/recommended.json +75 -8
  13. data/lib/datadog/appsec/assets/waf_rules/risky.json +1 -1
  14. data/lib/datadog/appsec/assets/waf_rules/strict.json +1 -1
  15. data/lib/datadog/appsec/assets.rb +1 -1
  16. data/lib/datadog/appsec/configuration/settings.rb +35 -22
  17. data/lib/datadog/appsec/configuration.rb +4 -2
  18. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  19. data/lib/datadog/appsec/contrib/configuration/settings.rb +1 -1
  20. data/lib/datadog/appsec/contrib/integration.rb +1 -1
  21. data/lib/datadog/appsec/contrib/patcher.rb +1 -1
  22. data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +1 -1
  23. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  24. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +1 -1
  25. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +1 -1
  26. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +1 -1
  27. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +1 -1
  28. data/lib/datadog/appsec/contrib/rack/request.rb +1 -1
  29. data/lib/datadog/appsec/contrib/rack/response.rb +1 -1
  30. data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +1 -1
  31. data/lib/datadog/appsec/contrib/rails/ext.rb +1 -1
  32. data/lib/datadog/appsec/contrib/rails/framework.rb +1 -1
  33. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +1 -1
  34. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +1 -1
  35. data/lib/datadog/appsec/contrib/rails/request.rb +1 -1
  36. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +1 -1
  37. data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +1 -1
  38. data/lib/datadog/appsec/contrib/sinatra/ext.rb +1 -1
  39. data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -1
  40. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +1 -1
  41. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +1 -1
  42. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +1 -1
  43. data/lib/datadog/appsec/event.rb +1 -1
  44. data/lib/datadog/appsec/extensions.rb +36 -26
  45. data/lib/datadog/appsec/instrumentation/gateway.rb +3 -3
  46. data/lib/datadog/appsec/processor.rb +15 -19
  47. data/lib/datadog/appsec/rate_limiter.rb +1 -1
  48. data/lib/datadog/appsec/reactive/address_hash.rb +1 -1
  49. data/lib/datadog/appsec/reactive/engine.rb +1 -1
  50. data/lib/datadog/appsec/reactive/operation.rb +2 -2
  51. data/lib/datadog/appsec/reactive/subscriber.rb +1 -1
  52. data/lib/datadog/appsec/response.rb +18 -9
  53. data/lib/datadog/appsec/utils/http/media_range.rb +201 -0
  54. data/lib/datadog/appsec/utils/http/media_type.rb +87 -0
  55. data/lib/datadog/appsec/utils/http.rb +9 -0
  56. data/lib/datadog/appsec/utils.rb +7 -0
  57. data/lib/datadog/appsec.rb +1 -1
  58. data/lib/datadog/ci/ext/environment.rb +57 -13
  59. data/lib/datadog/core/configuration/agent_settings_resolver.rb +2 -2
  60. data/lib/datadog/core/configuration/base.rb +3 -0
  61. data/lib/datadog/core/configuration/ext.rb +8 -0
  62. data/lib/datadog/core/configuration/option_definition.rb +11 -2
  63. data/lib/datadog/core/configuration/settings.rb +6 -4
  64. data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
  65. data/lib/datadog/core/metrics/client.rb +3 -2
  66. data/lib/datadog/core/metrics/ext.rb +0 -2
  67. data/lib/datadog/core/telemetry/collector.rb +1 -0
  68. data/lib/datadog/kit/appsec/events.rb +75 -0
  69. data/lib/datadog/kit/enable_core_dumps.rb +1 -0
  70. data/lib/datadog/kit/identity.rb +8 -7
  71. data/lib/datadog/opentelemetry/api/context.rb +187 -0
  72. data/lib/datadog/opentelemetry/api/trace/span.rb +15 -0
  73. data/lib/datadog/opentelemetry/sdk/configurator.rb +38 -0
  74. data/lib/datadog/opentelemetry/sdk/id_generator.rb +27 -0
  75. data/lib/datadog/opentelemetry/sdk/propagator.rb +91 -0
  76. data/lib/datadog/opentelemetry/sdk/span_processor.rb +92 -0
  77. data/lib/datadog/opentelemetry.rb +48 -0
  78. data/lib/datadog/tracing/configuration/ext.rb +1 -2
  79. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +5 -0
  80. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +10 -3
  81. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  82. data/lib/datadog/tracing/contrib/http/instrumentation.rb +3 -6
  83. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +5 -0
  84. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  85. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +3 -4
  86. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +5 -0
  87. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  88. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +3 -4
  89. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +44 -31
  90. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +33 -0
  91. data/lib/datadog/tracing/contrib/stripe/ext.rb +26 -0
  92. data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
  93. data/lib/datadog/tracing/contrib/stripe/patcher.rb +29 -0
  94. data/lib/datadog/tracing/contrib/stripe/request.rb +67 -0
  95. data/lib/datadog/tracing/contrib.rb +1 -0
  96. data/lib/datadog/tracing/distributed/trace_context.rb +16 -7
  97. data/lib/datadog/tracing/metadata/tagging.rb +6 -0
  98. data/lib/datadog/tracing/trace_digest.rb +17 -7
  99. data/lib/datadog/tracing/trace_operation.rb +8 -0
  100. data/lib/ddtrace/version.rb +1 -1
  101. metadata +23 -6
@@ -58,7 +58,7 @@ module Datadog
58
58
  end
59
59
 
60
60
  # Add additional response specific tags to the span.
61
- annotate_span_with_response!(span, response)
61
+ annotate_span_with_response!(span, response, request_options)
62
62
 
63
63
  # Invoke hook, if set.
64
64
  unless Contrib::HTTP::Instrumentation.after_request.nil?
@@ -90,15 +90,12 @@ module Datadog
90
90
  set_analytics_sample_rate(span, request_options)
91
91
  end
92
92
 
93
- def annotate_span_with_response!(span, response)
93
+ def annotate_span_with_response!(span, response, request_options)
94
94
  return unless response && response.code
95
95
 
96
96
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.code)
97
97
 
98
- case response.code.to_i
99
- when 400...599
100
- span.set_error(response)
101
- end
98
+ span.set_error(response) if request_options[:error_status_codes].include? response.code.to_i
102
99
  end
103
100
 
104
101
  def annotate_span_with_error!(span, error)
@@ -33,6 +33,11 @@ module Datadog
33
33
  o.lazy
34
34
  end
35
35
 
36
+ option :error_status_codes do |o|
37
+ o.default { env_to_list(Ext::ENV_ERROR_STATUS_CODES, 400...600, comma_separated_only: false) }
38
+ o.lazy
39
+ end
40
+
36
41
  option :split_by_domain, default: false
37
42
  end
38
43
  end
@@ -11,6 +11,7 @@ module Datadog
11
11
  ENV_SERVICE_NAME = 'DD_TRACE_HTTPCLIENT_SERVICE_NAME'.freeze
12
12
  ENV_ANALYTICS_ENABLED = 'DD_TRACE_HTTPCLIENT_ANALYTICS_ENABLED'.freeze
13
13
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_HTTPCLIENT_ANALYTICS_SAMPLE_RATE'.freeze
14
+ ENV_ERROR_STATUS_CODES = 'DD_TRACE_HTTPCLIENT_ERROR_STATUS_CODES'.freeze
14
15
  DEFAULT_PEER_SERVICE_NAME = 'httpclient'.freeze
15
16
  SPAN_REQUEST = 'httpclient.request'.freeze
16
17
  TAG_COMPONENT = 'httpclient'.freeze
@@ -42,7 +42,7 @@ module Datadog
42
42
  end
43
43
 
44
44
  # Add additional response specific tags to the span.
45
- annotate_span_with_response!(span, res)
45
+ annotate_span_with_response!(span, res, request_options)
46
46
 
47
47
  res
48
48
  end
@@ -72,13 +72,12 @@ module Datadog
72
72
  set_analytics_sample_rate(span, req_options)
73
73
  end
74
74
 
75
- def annotate_span_with_response!(span, response)
75
+ def annotate_span_with_response!(span, response, request_options)
76
76
  return unless response && response.status
77
77
 
78
78
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.status)
79
79
 
80
- case response.status.to_i
81
- when 400...599
80
+ if request_options[:error_status_codes].include? response.code.to_i
82
81
  span.set_error(["Error #{response.status}", response.body])
83
82
  end
84
83
  end
@@ -33,6 +33,11 @@ module Datadog
33
33
  o.lazy
34
34
  end
35
35
 
36
+ option :error_status_codes do |o|
37
+ o.default { env_to_list(Ext::ENV_ERROR_STATUS_CODES, 400...600, comma_separated_only: false) }
38
+ o.lazy
39
+ end
40
+
36
41
  option :split_by_domain, default: false
37
42
  end
38
43
  end
@@ -11,6 +11,7 @@ module Datadog
11
11
  ENV_SERVICE_NAME = 'DD_TRACE_HTTPRB_SERVICE_NAME'.freeze
12
12
  ENV_ANALYTICS_ENABLED = 'DD_TRACE_HTTPRB_ANALYTICS_ENABLED'.freeze
13
13
  ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_EHTTPRB_ANALYTICS_SAMPLE_RATE'.freeze
14
+ ENV_ERROR_STATUS_CODES = 'DD_TRACE_HTTPCLIENT_ERROR_STATUS_CODES'.freeze
14
15
  DEFAULT_PEER_SERVICE_NAME = 'httprb'.freeze
15
16
  SPAN_REQUEST = 'httprb.request'.freeze
16
17
  TAG_COMPONENT = 'httprb'.freeze
@@ -42,7 +42,7 @@ module Datadog
42
42
  end
43
43
 
44
44
  # Add additional response specific tags to the span.
45
- annotate_span_with_response!(span, res)
45
+ annotate_span_with_response!(span, res, request_options)
46
46
 
47
47
  res
48
48
  end
@@ -81,13 +81,12 @@ module Datadog
81
81
  set_analytics_sample_rate(span, req_options)
82
82
  end
83
83
 
84
- def annotate_span_with_response!(span, response)
84
+ def annotate_span_with_response!(span, response, request_options)
85
85
  return unless response && response.code
86
86
 
87
87
  span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.code)
88
88
 
89
- case response.code.to_i
90
- when 400...599
89
+ if request_options[:error_status_codes].include? response.code.to_i
91
90
  # https://github.com/DataDog/dd-trace-rb/issues/1116
92
91
  # parsing the response body message will alter downstream application behavior
93
92
  span.set_error(["Error #{response.code}", 'Error'])
@@ -20,63 +20,66 @@ 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
 
@@ -101,9 +104,18 @@ module Datadog
101
104
  )
102
105
  end
103
106
 
104
- result = yield(propagated_sql_statement)
105
- annotate_span_with_result!(span, result)
106
- 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
107
119
  end
108
120
  end
109
121
 
@@ -128,6 +140,7 @@ module Datadog
128
140
  span.set_tag(Tracing::Metadata::Ext::NET::TAG_DESTINATION_PORT, port)
129
141
  end
130
142
 
143
+ # @param [PG::Result] result
131
144
  def annotate_span_with_result!(span, result)
132
145
  span.set_tag(Contrib::Ext::DB::TAG_ROW_COUNT, result.ntuples)
133
146
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../configuration/settings'
4
+ require_relative '../ext'
5
+
6
+ module Datadog
7
+ module Tracing
8
+ module Contrib
9
+ module Stripe
10
+ module Configuration
11
+ # Custom settings for the Stripe integration
12
+ # @public_api
13
+ class Settings < Contrib::Configuration::Settings
14
+ option :enabled do |o|
15
+ o.default { env_to_bool(Ext::ENV_ENABLED, true) }
16
+ o.lazy
17
+ end
18
+
19
+ option :analytics_enabled do |o|
20
+ o.default { env_to_bool(Ext::ENV_ANALYTICS_ENABLED, false) }
21
+ o.lazy
22
+ end
23
+
24
+ option :analytics_sample_rate do |o|
25
+ o.default { env_to_float(Ext::ENV_ANALYTICS_SAMPLE_RATE, 1.0) }
26
+ o.lazy
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Tracing
5
+ module Contrib
6
+ module Stripe
7
+ # Stripe integration constants
8
+ # @public_api Changing resource names, tag names, or environment variables creates breaking changes.
9
+ module Ext
10
+ ENV_ENABLED = 'DD_TRACE_STRIPE_ENABLED'
11
+ ENV_ANALYTICS_ENABLED = 'DD_TRACE_STRIPE_ANALYTICS_ENABLED'
12
+ ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_STRIPE_ANALYTICS_SAMPLE_RATE'
13
+ SPAN_REQUEST = 'stripe.request'
14
+ SPAN_TYPE_REQUEST = 'custom'
15
+ TAG_COMPONENT = 'stripe'
16
+ TAG_OPERATION_REQUEST = 'request'
17
+ TAG_REQUEST_HTTP_STATUS = 'stripe.request.http_status'
18
+ TAG_REQUEST_ID = 'stripe.request.id'
19
+ TAG_REQUEST_METHOD = 'stripe.request.method'
20
+ TAG_REQUEST_NUM_RETRIES = 'stripe.request.num_retries'
21
+ TAG_REQUEST_PATH = 'stripe.request.path'
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../integration'
4
+ require_relative 'configuration/settings'
5
+ require_relative 'patcher'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ module Stripe
11
+ # Description of Stripe integration
12
+ class Integration
13
+ include Contrib::Integration
14
+
15
+ MINIMUM_VERSION = Gem::Version.new('5.15.0')
16
+
17
+ # @public_api Changing the integration name or integration options can cause breaking changes
18
+ register_as :stripe
19
+
20
+ def self.version
21
+ Gem.loaded_specs['stripe'] && Gem.loaded_specs['stripe'].version
22
+ end
23
+
24
+ def self.loaded?
25
+ !defined?(::Stripe).nil?
26
+ end
27
+
28
+ def self.compatible?
29
+ super && version >= MINIMUM_VERSION
30
+ end
31
+
32
+ def new_configuration
33
+ Configuration::Settings.new
34
+ end
35
+
36
+ def patcher
37
+ Patcher
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ require_relative '../patcher'
5
+ require_relative 'request'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ module Stripe
11
+ # Provides instrumentation for `stripe` through the Stripe instrumentation framework
12
+ module Patcher
13
+ include Contrib::Patcher
14
+
15
+ module_function
16
+
17
+ def target_version
18
+ Integration.version
19
+ end
20
+
21
+ def patch
22
+ ::Stripe::Instrumentation.subscribe(:request_begin, :datadog_tracing) { |event| Request.start_span(event) }
23
+ ::Stripe::Instrumentation.subscribe(:request_end, :datadog_tracing) { |event| Request.finish_span(event) }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../metadata/ext'
4
+ require_relative '../../analytics'
5
+ require_relative 'ext'
6
+
7
+ module Datadog
8
+ module Tracing
9
+ module Contrib
10
+ module Stripe
11
+ # Defines instrumentation for Stripe requests
12
+ module Request
13
+ module_function
14
+
15
+ def start_span(event)
16
+ # Start a trace
17
+ Tracing.trace(Ext::SPAN_REQUEST).tap do |span|
18
+ event.user_data[:datadog_span] = span
19
+ end
20
+ end
21
+
22
+ def finish_span(event)
23
+ span = event.user_data[:datadog_span]
24
+ # If no active span, return.
25
+ return nil if span.nil?
26
+
27
+ begin
28
+ tag_span(span, event)
29
+ ensure
30
+ # Finish the span
31
+ span.finish
32
+ end
33
+ end
34
+
35
+ def tag_span(span, event)
36
+ # dependent upon stripe/stripe-ruby#1168
37
+ span.resource = "stripe.#{event.object_name}" if event.respond_to?(:object_name) && event.object_name
38
+
39
+ span.span_type = Ext::SPAN_TYPE_REQUEST
40
+ span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
41
+ span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_REQUEST)
42
+
43
+ # Set analytics sample rate
44
+ if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
45
+ Contrib::Analytics.set_sample_rate(span, configuration[:analytics_sample_rate])
46
+ end
47
+
48
+ # Measure service stats
49
+ Contrib::Analytics.set_measured(span)
50
+
51
+ span.set_tag(Ext::TAG_REQUEST_ID, event.request_id)
52
+ span.set_tag(Ext::TAG_REQUEST_HTTP_STATUS, event.http_status.to_s)
53
+ span.set_tag(Ext::TAG_REQUEST_METHOD, event.method)
54
+ span.set_tag(Ext::TAG_REQUEST_PATH, event.path)
55
+ span.set_tag(Ext::TAG_REQUEST_NUM_RETRIES, event.num_retries.to_s)
56
+ rescue StandardError => e
57
+ Datadog.logger.debug(e.message)
58
+ end
59
+
60
+ def configuration
61
+ Datadog.configuration.tracing[:stripe]
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -75,4 +75,5 @@ require_relative 'contrib/shoryuken/integration'
75
75
  require_relative 'contrib/sidekiq/integration'
76
76
  require_relative 'contrib/sinatra/integration'
77
77
  require_relative 'contrib/sneakers/integration'
78
+ require_relative 'contrib/stripe/integration'
78
79
  require_relative 'contrib/sucker_punch/integration'
@@ -43,7 +43,7 @@ module Datadog
43
43
 
44
44
  return unless trace_id # Could not parse traceparent
45
45
 
46
- tracestate, sampling_priority, origin, tags = extract_tracestate(fetcher[@tracestate_key])
46
+ tracestate, sampling_priority, origin, tags, unknown_fields = extract_tracestate(fetcher[@tracestate_key])
47
47
 
48
48
  sampling_priority = parse_priority_sampling(sampled, sampling_priority)
49
49
 
@@ -54,8 +54,9 @@ module Datadog
54
54
  trace_sampling_priority: sampling_priority,
55
55
  trace_distributed_tags: tags,
56
56
  trace_distributed_id: trace_id,
57
+ trace_flags: trace_flags,
57
58
  trace_state: tracestate,
58
- trace_flags: trace_flags
59
+ trace_state_unknown_fields: unknown_fields,
59
60
  )
60
61
  end
61
62
 
@@ -152,6 +153,8 @@ module Datadog
152
153
  end
153
154
  end
154
155
 
156
+ tracestate << digest.trace_state_unknown_fields if digest.trace_state_unknown_fields
157
+
155
158
  # Is there any Datadog-specific information to propagate.
156
159
  # Check for > 3 size because the empty prefix `dd=` has 3 characters.
157
160
  if tracestate.size > 3
@@ -268,21 +271,23 @@ module Datadog
268
271
  vendors = split_tracestate(tracestate)
269
272
 
270
273
  # Find Datadog's `dd=` tracestate field.
271
- dd_tracestate = vendors.find { |v| v.start_with?('dd=') }
272
- return tracestate unless dd_tracestate
274
+ idx = vendors.index { |v| v.start_with?('dd=') }
275
+ return tracestate unless idx
273
276
 
274
277
  # Delete `dd=` prefix
278
+ dd_tracestate = vendors.delete_at(idx)
275
279
  dd_tracestate.slice!(0..2)
276
280
 
277
- origin, sampling_priority, tags = extract_datadog_fields(dd_tracestate)
281
+ origin, sampling_priority, tags, unknown_fields = extract_datadog_fields(dd_tracestate)
278
282
 
279
- [tracestate, sampling_priority, origin, tags]
283
+ [vendors.join(','), sampling_priority, origin, tags, unknown_fields]
280
284
  end
281
285
 
282
286
  def extract_datadog_fields(dd_tracestate)
283
287
  sampling_priority = nil
284
288
  origin = nil
285
289
  tags = nil
290
+ unknown_fields = nil
286
291
 
287
292
  # DEV: Since Ruby 2.6 `split` can receive a block, so `each` can be removed then.
288
293
  dd_tracestate.split(';').each do |pair|
@@ -299,10 +304,14 @@ module Datadog
299
304
 
300
305
  tags ||= {}
301
306
  tags["#{Tracing::Metadata::Ext::Distributed::TAGS_PREFIX}#{key}"] = value
307
+ else
308
+ unknown_fields ||= String.new
309
+ unknown_fields << pair
310
+ unknown_fields << ';'
302
311
  end
303
312
  end
304
313
 
305
- [origin, sampling_priority, tags]
314
+ [origin, sampling_priority, tags, unknown_fields]
306
315
  end
307
316
 
308
317
  # Restore `:` back to `=`.
@@ -110,6 +110,12 @@ module Datadog
110
110
  metrics.delete(key)
111
111
  end
112
112
 
113
+ # Returns a copy of all metadata.
114
+ # Keys for `@meta` and `@metrics` don't collide, by construction.
115
+ def tags
116
+ @meta.merge(@metrics)
117
+ end
118
+
113
119
  protected
114
120
 
115
121
  def meta
@@ -59,15 +59,22 @@ module Datadog
59
59
  # This attribute will preserve the original id, while `trace_id` will only contain the lower 64 bits.
60
60
  # @return [Integer]
61
61
  # @see https://www.w3.org/TR/trace-context/#trace-id
62
- # @!attribute [r] trace_tracestate
63
- # The W3C "tracestate" extracted from a distributed context.
64
- # This field is a string representing vendor-specific distribution data.
65
- # @return [String]
66
- # @see https://www.w3.org/TR/trace-context/#tracestate-header
67
62
  # @!attribute [r] trace_flags
68
63
  # The W3C "trace-flags" extracted from a distributed context. This field is an 8-bit unsigned integer.
69
64
  # @return [Integer]
70
65
  # @see https://www.w3.org/TR/trace-context/#trace-flags
66
+ # @!attribute [r] trace_state
67
+ # The W3C "tracestate" extracted from a distributed context.
68
+ # This field is a string representing vendor-specific distribution data.
69
+ # The `dd=` entry is removed from `trace_state` as its value is dynamically calculated
70
+ # on every propagation injection.
71
+ # @return [String]
72
+ # @see https://www.w3.org/TR/trace-context/#tracestate-header
73
+ # @!attribute [r] trace_state_unknown_fields
74
+ # From W3C "tracestate"'s `dd=` entry, when keys are not recognized they are stored here long with their values.
75
+ # This allows later propagation to include those unknown fields, as they can represent future versions of the spec
76
+ # sending data through this service. This value ends in a trailing `;` to facilitate serialization.
77
+ # @return [String]
71
78
  # TODO: The documentation for the last attribute above won't be rendered.
72
79
  # TODO: This might be a YARD bug as adding an attribute, making it now second-last attribute, renders correctly.
73
80
  attr_reader \
@@ -88,7 +95,8 @@ module Datadog
88
95
  :trace_service,
89
96
  :trace_distributed_id,
90
97
  :trace_flags,
91
- :trace_state
98
+ :trace_state,
99
+ :trace_state_unknown_fields
92
100
 
93
101
  def initialize(
94
102
  span_id: nil,
@@ -108,7 +116,8 @@ module Datadog
108
116
  trace_service: nil,
109
117
  trace_distributed_id: nil,
110
118
  trace_flags: nil,
111
- trace_state: nil
119
+ trace_state: nil,
120
+ trace_state_unknown_fields: nil
112
121
  )
113
122
  @span_id = span_id
114
123
  @span_name = span_name && span_name.dup.freeze
@@ -128,6 +137,7 @@ module Datadog
128
137
  @trace_distributed_id = trace_distributed_id
129
138
  @trace_flags = trace_flags
130
139
  @trace_state = trace_state && trace_state.dup.freeze
140
+ @trace_state_unknown_fields = trace_state_unknown_fields && trace_state_unknown_fields.dup.freeze
131
141
 
132
142
  freeze
133
143
  end
@@ -463,6 +463,14 @@ module Datadog
463
463
  def distributed_tags
464
464
  meta.select { |name, _| name.start_with?(Metadata::Ext::Distributed::TAGS_PREFIX) }
465
465
  end
466
+
467
+ def reset
468
+ @root_span = nil
469
+ @active_span = nil
470
+ @active_span_count = 0
471
+ @finished = false
472
+ @spans = []
473
+ end
466
474
  end
467
475
  end
468
476
  end
@@ -3,7 +3,7 @@
3
3
  module DDTrace
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 8
6
+ MINOR = 9
7
7
  PATCH = 0
8
8
  PRE = nil
9
9