ddtrace 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
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