ddtrace 1.4.1 → 1.6.1

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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +144 -1
  3. data/LICENSE-3rdparty.csv +1 -0
  4. data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +9 -2
  5. data/ext/ddtrace_profiling_loader/extconf.rb +17 -0
  6. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +38 -2
  7. data/ext/ddtrace_profiling_native_extension/clock_id.h +1 -0
  8. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +1 -0
  9. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +517 -42
  10. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +3 -0
  11. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +208 -30
  12. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +156 -46
  13. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +11 -2
  14. data/ext/ddtrace_profiling_native_extension/extconf.rb +11 -1
  15. data/ext/ddtrace_profiling_native_extension/http_transport.c +83 -64
  16. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +4 -4
  17. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +3 -4
  18. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +59 -0
  19. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +3 -0
  20. data/ext/ddtrace_profiling_native_extension/profiling.c +10 -0
  21. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +0 -1
  22. data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +4 -2
  23. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +45 -29
  24. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +7 -7
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +1169 -275
  26. data/lib/datadog/appsec/assets/waf_rules/risky.json +78 -78
  27. data/lib/datadog/appsec/assets/waf_rules/strict.json +278 -88
  28. data/lib/datadog/appsec/configuration/settings.rb +0 -2
  29. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +25 -20
  30. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +11 -11
  31. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +11 -11
  32. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +11 -11
  33. data/lib/datadog/appsec/contrib/rack/request.rb +3 -0
  34. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +46 -19
  35. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -6
  36. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  37. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +11 -11
  38. data/lib/datadog/appsec/contrib/rails/request.rb +3 -0
  39. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +14 -12
  40. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +11 -11
  41. data/lib/datadog/appsec/event.rb +6 -10
  42. data/lib/datadog/appsec/instrumentation/gateway.rb +16 -2
  43. data/lib/datadog/appsec/processor.rb +18 -2
  44. data/lib/datadog/ci/ext/environment.rb +16 -4
  45. data/lib/datadog/core/configuration/agent_settings_resolver.rb +0 -3
  46. data/lib/datadog/core/configuration/components.rb +28 -16
  47. data/lib/datadog/core/configuration/settings.rb +127 -8
  48. data/lib/datadog/core/configuration.rb +1 -1
  49. data/lib/datadog/core/diagnostics/environment_logger.rb +5 -1
  50. data/lib/datadog/core/header_collection.rb +41 -0
  51. data/lib/datadog/core/telemetry/collector.rb +0 -2
  52. data/lib/datadog/core/utils/compression.rb +5 -1
  53. data/lib/datadog/core/workers/async.rb +0 -2
  54. data/lib/datadog/core.rb +0 -54
  55. data/lib/datadog/opentracer/tracer.rb +4 -6
  56. data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +12 -2
  57. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -3
  58. data/lib/datadog/profiling/collectors/old_stack.rb +1 -1
  59. data/lib/datadog/profiling/exporter.rb +2 -4
  60. data/lib/datadog/profiling/http_transport.rb +1 -1
  61. data/lib/datadog/profiling.rb +1 -1
  62. data/lib/datadog/tracing/client_ip.rb +164 -0
  63. data/lib/datadog/tracing/configuration/ext.rb +14 -0
  64. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +2 -0
  65. data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
  66. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  67. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +4 -0
  68. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +2 -0
  69. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -0
  70. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +2 -2
  71. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +2 -0
  72. data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -0
  73. data/lib/datadog/tracing/contrib/ext.rb +25 -0
  74. data/lib/datadog/tracing/contrib/faraday/middleware.rb +3 -2
  75. data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -2
  76. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -1
  77. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +5 -0
  78. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +7 -1
  79. data/lib/datadog/tracing/contrib/grpc/ext.rb +2 -0
  80. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
  81. data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +22 -0
  82. data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
  83. data/lib/datadog/tracing/contrib/hanami/integration.rb +44 -0
  84. data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
  85. data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
  86. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
  87. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +44 -0
  88. data/lib/datadog/tracing/contrib/http/instrumentation.rb +2 -0
  89. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +2 -0
  90. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +2 -0
  91. data/lib/datadog/tracing/contrib/mongodb/ext.rb +7 -0
  92. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +4 -0
  93. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +12 -0
  94. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  95. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -0
  96. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +12 -0
  97. data/lib/datadog/tracing/contrib/pg/ext.rb +2 -1
  98. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +38 -21
  99. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +43 -0
  100. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +32 -0
  101. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +28 -0
  102. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +49 -0
  103. data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
  104. data/lib/datadog/tracing/contrib/rack/middlewares.rb +105 -43
  105. data/lib/datadog/tracing/contrib/redis/ext.rb +2 -0
  106. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +4 -2
  107. data/lib/datadog/tracing/contrib/redis/integration.rb +2 -1
  108. data/lib/datadog/tracing/contrib/redis/patcher.rb +40 -0
  109. data/lib/datadog/tracing/contrib/redis/tags.rb +5 -0
  110. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +2 -0
  111. data/lib/datadog/tracing/contrib/sinatra/env.rb +12 -23
  112. data/lib/datadog/tracing/contrib/sinatra/ext.rb +7 -3
  113. data/lib/datadog/tracing/contrib/sinatra/patcher.rb +2 -2
  114. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +8 -80
  115. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +14 -9
  116. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +92 -10
  117. data/lib/datadog/tracing/contrib.rb +1 -0
  118. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +84 -0
  119. data/lib/datadog/tracing/distributed/headers/datadog.rb +122 -30
  120. data/lib/datadog/tracing/distributed/headers/ext.rb +2 -0
  121. data/lib/datadog/tracing/flush.rb +57 -35
  122. data/lib/datadog/tracing/metadata/ext.rb +11 -9
  123. data/lib/datadog/tracing/metadata/tagging.rb +9 -0
  124. data/lib/datadog/tracing/propagation/http.rb +9 -1
  125. data/lib/datadog/tracing/sampling/ext.rb +31 -0
  126. data/lib/datadog/tracing/sampling/priority_sampler.rb +46 -4
  127. data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +8 -9
  128. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +29 -5
  129. data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -0
  130. data/lib/datadog/tracing/sampling/rate_sampler.rb +20 -3
  131. data/lib/datadog/tracing/sampling/rule_sampler.rb +4 -3
  132. data/lib/datadog/tracing/sampling/span/ext.rb +25 -0
  133. data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
  134. data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
  135. data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
  136. data/lib/datadog/tracing/sampling/span/sampler.rb +75 -0
  137. data/lib/datadog/tracing/span_operation.rb +0 -2
  138. data/lib/datadog/tracing/trace_digest.rb +3 -0
  139. data/lib/datadog/tracing/trace_operation.rb +32 -3
  140. data/lib/datadog/tracing/trace_segment.rb +7 -2
  141. data/lib/datadog/tracing/tracer.rb +34 -6
  142. data/lib/datadog/tracing/writer.rb +7 -0
  143. data/lib/ddtrace/transport/trace_formatter.rb +7 -0
  144. data/lib/ddtrace/transport/traces.rb +3 -1
  145. data/lib/ddtrace/version.rb +1 -1
  146. metadata +36 -18
  147. data/lib/datadog/profiling/old_ext.rb +0 -42
  148. data/lib/datadog/profiling/transport/http/api/endpoint.rb +0 -85
  149. data/lib/datadog/profiling/transport/http/api/instance.rb +0 -38
  150. data/lib/datadog/profiling/transport/http/api/spec.rb +0 -42
  151. data/lib/datadog/profiling/transport/http/api.rb +0 -45
  152. data/lib/datadog/profiling/transport/http/builder.rb +0 -30
  153. data/lib/datadog/profiling/transport/http/client.rb +0 -37
  154. data/lib/datadog/profiling/transport/http/response.rb +0 -21
  155. data/lib/datadog/profiling/transport/http.rb +0 -118
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative 'ext'
6
+ require_relative 'matcher'
7
+ require_relative 'rule'
8
+
9
+ module Datadog
10
+ module Tracing
11
+ module Sampling
12
+ module Span
13
+ # Converts user configuration into {Datadog::Tracing::Sampling::Span::Rule} objects,
14
+ # handling any parsing errors.
15
+ module RuleParser
16
+ class << self
17
+ # Parses the provided JSON string containing the Single Span
18
+ # Sampling configuration list.
19
+ # In case of parsing errors, `nil` is returned.
20
+ #
21
+ # @param rules [String] the JSON configuration rules to be parsed
22
+ # @return [Array<Datadog::Tracing::Sampling::Span::Rule>] a list of parsed rules
23
+ # @return [nil] if parsing failed
24
+ def parse_json(rules)
25
+ return nil unless rules
26
+
27
+ begin
28
+ list = JSON.parse(rules)
29
+ rescue => e
30
+ Datadog.logger.warn(
31
+ "Error parsing Span Sampling Rules `#{rules.inspect}`: "\
32
+ "#{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
33
+ )
34
+ return nil
35
+ end
36
+
37
+ parse_list(list)
38
+ end
39
+
40
+ # Parses a list of Hashes containing the parsed JSON information
41
+ # for Single Span Sampling configuration.
42
+ # In case of parsing errors, `nil` is returned.
43
+ #
44
+ # @param rules [Array<String] the JSON configuration rules to be parsed
45
+ # @return [Array<Datadog::Tracing::Sampling::Span::Rule>] a list of parsed rules
46
+ # @return [nil] if parsing failed
47
+ def parse_list(rules)
48
+ unless rules.is_a?(Array)
49
+ Datadog.logger.warn("Span Sampling Rules are not an array: #{rules.inspect}")
50
+ return nil
51
+ end
52
+
53
+ parsed = rules.map do |hash|
54
+ unless hash.is_a?(Hash)
55
+ Datadog.logger.warn("Span Sampling Rule is not a key-value object: #{hash.inspect}")
56
+ return nil
57
+ end
58
+
59
+ begin
60
+ parse_rule(hash)
61
+ rescue => e
62
+ Datadog.logger.warn(
63
+ "Cannot parse Span Sampling Rule #{hash.inspect}: " \
64
+ "#{e.class.name} #{e} at #{Array(e.backtrace).first}"
65
+ )
66
+ return nil
67
+ end
68
+ end
69
+
70
+ parsed.compact!
71
+ parsed
72
+ end
73
+
74
+ private
75
+
76
+ def parse_rule(hash)
77
+ matcher_options = {}
78
+ if (name_pattern = hash['name'])
79
+ matcher_options[:name_pattern] = name_pattern
80
+ end
81
+
82
+ if (service_pattern = hash['service'])
83
+ matcher_options[:service_pattern] = service_pattern
84
+ end
85
+
86
+ matcher = Matcher.new(**matcher_options)
87
+
88
+ rule_options = {}
89
+ if (sample_rate = hash['sample_rate'])
90
+ rule_options[:sample_rate] = sample_rate
91
+ end
92
+
93
+ if (max_per_second = hash['max_per_second'])
94
+ rule_options[:rate_limit] = max_per_second
95
+ end
96
+
97
+ Rule.new(matcher, **rule_options)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,75 @@
1
+ module Datadog
2
+ module Tracing
3
+ module Sampling
4
+ module Span
5
+ # Applies Single Span Sampling rules to spans.
6
+ # When matching the configured rules, a span is ensured to
7
+ # be processed Datadog App. In other words, a single sampled span
8
+ # will never be dropped by the tracer or Datadog agent.
9
+ #
10
+ # All spans in a trace are subject to the single sampling rules, if
11
+ # any rules are configured.
12
+ #
13
+ # Single Span Sampling is distinct from trace-level sampling:
14
+ # Single Span Sampling can ensure a span is kept, even if its
15
+ # enclosing trace is rejected by trace-level sampling.
16
+ #
17
+ # This class only applies operations to spans that are part
18
+ # of traces that was rejected by trace sampling.
19
+ # A trace is rejected if either of the following conditions is true:
20
+ # * The priority sampling for a trace is set to either {USER_REJECT} or {AUTO_REJECT}.
21
+ # * The trace was rejected by internal sampling, thus never flushed.
22
+ #
23
+ # Single-sampled spans are tagged and the tracer ensures they will
24
+ # reach the Datadog App, regardless of their enclosing trace sampling decision.
25
+ #
26
+ # Single Span Sampling does not inspect spans that are part of a trace
27
+ # that has been accepted by trace-level sampling rules: all spans from such
28
+ # trace are guaranteed to reach the Datadog App.
29
+ class Sampler
30
+ attr_reader :rules
31
+
32
+ # Receives sampling rules to apply to individual spans.
33
+ #
34
+ # @param [Array<Datadog::Tracing::Sampling::Span::Rule>] rules list of rules to apply to spans
35
+ def initialize(rules = [])
36
+ @rules = rules
37
+ end
38
+
39
+ # Applies Single Span Sampling rules to the span if the trace has been rejected.
40
+ #
41
+ # The trace can be outright rejected, and never reach the transport,
42
+ # or be set as rejected by priority sampling. In both cases, the trace
43
+ # is considered rejected for Single Span Sampling purposes.
44
+ #
45
+ # If multiple rules match, only the first one is applied.
46
+ #
47
+ # @param [Datadog::Tracing::TraceOperation] trace_op trace for the provided span
48
+ # @param [Datadog::Tracing::SpanOperation] span_op Span to apply sampling rules
49
+ # @return [void]
50
+ def sample!(trace_op, span_op)
51
+ return if trace_op.sampled? && trace_op.priority_sampled?
52
+
53
+ # Applies the first matching rule
54
+ @rules.each do |rule|
55
+ decision = rule.sample!(span_op)
56
+
57
+ next if decision == :not_matched # Iterate until we find a matching decision
58
+
59
+ if decision == :kept
60
+ trace_op.set_tag(
61
+ Metadata::Ext::Distributed::TAG_DECISION_MAKER,
62
+ Sampling::Ext::Decision::SPAN_SAMPLING_RATE
63
+ )
64
+ end
65
+
66
+ break # Found either a `kept` or `rejected` decision
67
+ end
68
+
69
+ nil
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -18,7 +18,6 @@ module Datadog
18
18
  # It gives a Span a context which can be used to
19
19
  # build a Span. When completed, it yields the Span.
20
20
  #
21
- # rubocop:disable Metrics/ClassLength
22
21
  # @public_api
23
22
  class SpanOperation
24
23
  include Metadata
@@ -516,6 +515,5 @@ module Datadog
516
515
  alias :span_type :type
517
516
  alias :span_type= :type=
518
517
  end
519
- # rubocop:enable Metrics/ClassLength
520
518
  end
521
519
  end
@@ -12,6 +12,7 @@ module Datadog
12
12
  :span_resource,
13
13
  :span_service,
14
14
  :span_type,
15
+ :trace_distributed_tags,
15
16
  :trace_hostname,
16
17
  :trace_id,
17
18
  :trace_name,
@@ -28,6 +29,7 @@ module Datadog
28
29
  span_resource: nil,
29
30
  span_service: nil,
30
31
  span_type: nil,
32
+ trace_distributed_tags: nil,
31
33
  trace_hostname: nil,
32
34
  trace_id: nil,
33
35
  trace_name: nil,
@@ -43,6 +45,7 @@ module Datadog
43
45
  @span_resource = span_resource && span_resource.dup.freeze
44
46
  @span_service = span_service && span_service.dup.freeze
45
47
  @span_type = span_type && span_type.dup.freeze
48
+ @trace_distributed_tags = trace_distributed_tags && trace_distributed_tags.dup.freeze
46
49
  @trace_hostname = trace_hostname && trace_hostname.dup.freeze
47
50
  @trace_id = trace_id
48
51
  @trace_name = trace_name && trace_name.dup.freeze
@@ -22,7 +22,6 @@ module Datadog
22
22
  # For async support, a {Datadog::Tracing::TraceOperation} should be employed
23
23
  # per execution context (e.g. Thread, etc.)
24
24
  #
25
- # rubocop:disable Metrics/ClassLength
26
25
  # @public_api
27
26
  class TraceOperation
28
27
  include Metadata::Tagging
@@ -113,18 +112,34 @@ module Datadog
113
112
  @finished == true
114
113
  end
115
114
 
115
+ # Will this trace be flushed by the tracer transport?
116
+ # This includes cases where the span is kept solely due to priority sampling.
117
+ #
118
+ # This is not the ultimate Datadog App sampling decision. Downstream systems
119
+ # can decide to reject this trace, especially for cases where priority
120
+ # sampling is set to AUTO_KEEP.
121
+ #
122
+ # @return [Boolean]
116
123
  def sampled?
117
- @sampled == true || (!@sampling_priority.nil? && @sampling_priority > 0)
124
+ @sampled == true || priority_sampled?
125
+ end
126
+
127
+ # Has the priority sampling chosen to keep this span?
128
+ # @return [Boolean]
129
+ def priority_sampled?
130
+ !@sampling_priority.nil? && @sampling_priority > 0
118
131
  end
119
132
 
120
133
  def keep!
121
134
  self.sampled = true
122
135
  self.sampling_priority = Sampling::Ext::Priority::USER_KEEP
136
+ set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, Tracing::Sampling::Ext::Decision::MANUAL)
123
137
  end
124
138
 
125
139
  def reject!
126
140
  self.sampled = false
127
141
  self.sampling_priority = Sampling::Ext::Priority::USER_REJECT
142
+ set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, Tracing::Sampling::Ext::Decision::MANUAL)
128
143
  end
129
144
 
130
145
  def name
@@ -233,6 +248,11 @@ module Datadog
233
248
  end
234
249
  end
235
250
 
251
+ # Returns a {TraceSegment} with all finished spans that can be flushed
252
+ # at invocation time. All other **finished** spans are discarded.
253
+ #
254
+ # @yield [spans] spans that will be returned as part of the trace segment returned
255
+ # @return [TraceSegment]
236
256
  def flush!
237
257
  finished = finished?
238
258
 
@@ -240,6 +260,8 @@ module Datadog
240
260
  spans = @spans.dup
241
261
  @spans = []
242
262
 
263
+ spans = yield(spans) if block_given?
264
+
243
265
  # Use them to build a trace
244
266
  build_trace(spans, !finished)
245
267
  end
@@ -258,6 +280,7 @@ module Datadog
258
280
  span_resource: (@active_span && @active_span.resource),
259
281
  span_service: (@active_span && @active_span.service),
260
282
  span_type: (@active_span && @active_span.type),
283
+ trace_distributed_tags: distributed_tags,
261
284
  trace_hostname: @hostname,
262
285
  trace_id: @id,
263
286
  trace_name: name,
@@ -432,7 +455,13 @@ module Datadog
432
455
  root_span_id: !partial ? root_span && root_span.id : nil
433
456
  )
434
457
  end
458
+
459
+ # Returns tracer tags that will be propagated if this span's context
460
+ # is exported through {.to_digest}.
461
+ # @return [Hash] key value pairs of distributed tags
462
+ def distributed_tags
463
+ meta.select { |name, _| name.start_with?(Metadata::Ext::Distributed::TAGS_PREFIX) }
464
+ end
435
465
  end
436
- # rubocop:enable Metrics/ClassLength
437
466
  end
438
467
  end
@@ -11,7 +11,6 @@ module Datadog
11
11
  module Tracing
12
12
  # Serializable construct representing a trace
13
13
  # @public_api
14
- # rubocop:disable Metrics/ClassLength
15
14
  class TraceSegment
16
15
  TAG_NAME = 'name'.freeze
17
16
  TAG_RESOURCE = 'resource'.freeze
@@ -31,11 +30,13 @@ module Datadog
31
30
  :rule_sample_rate,
32
31
  :runtime_id,
33
32
  :sample_rate,
33
+ :sampling_decision_maker,
34
34
  :sampling_priority,
35
35
  :service
36
36
 
37
37
  # rubocop:disable Metrics/CyclomaticComplexity
38
38
  # rubocop:disable Metrics/PerceivedComplexity
39
+ # @param spans [Array<Datadog::Span>]
39
40
  def initialize(
40
41
  spans,
41
42
  agent_sample_rate: nil,
@@ -77,6 +78,7 @@ module Datadog
77
78
  @rule_sample_rate = rule_sample_rate_tag || rule_sample_rate
78
79
  @runtime_id = runtime_id || runtime_id_tag
79
80
  @sample_rate = sample_rate || sample_rate_tag
81
+ @sampling_decision_maker = sampling_decision_maker_tag
80
82
  @sampling_priority = sampling_priority || sampling_priority_tag
81
83
  @service = Core::Utils::SafeDup.frozen_or_dup(service || service_tag)
82
84
  end
@@ -194,6 +196,10 @@ module Datadog
194
196
  metrics[Metadata::Ext::Sampling::TAG_SAMPLE_RATE]
195
197
  end
196
198
 
199
+ def sampling_decision_maker_tag
200
+ meta[Metadata::Ext::Distributed::TAG_DECISION_MAKER]
201
+ end
202
+
197
203
  def sampling_priority_tag
198
204
  meta[Metadata::Ext::Distributed::TAG_SAMPLING_PRIORITY]
199
205
  end
@@ -202,6 +208,5 @@ module Datadog
202
208
  meta[TAG_SERVICE]
203
209
  end
204
210
  end
205
- # rubocop:enable Metrics/ClassLength
206
211
  end
207
212
  end
@@ -11,6 +11,7 @@ require_relative 'context_provider'
11
11
  require_relative 'sampling/all_sampler'
12
12
  require_relative 'sampling/rule_sampler'
13
13
  require_relative 'sampling/priority_sampler'
14
+ require_relative 'sampling/span/sampler'
14
15
  require_relative 'span_operation'
15
16
  require_relative 'trace_digest'
16
17
  require_relative 'trace_operation'
@@ -22,12 +23,12 @@ module Datadog
22
23
  # example, a trace can be used to track the entire time spent processing a complicated web request.
23
24
  # Even though the request may require multiple resources and machines to handle the request, all
24
25
  # of these function calls and sub-requests would be encapsulated within a single trace.
25
- # rubocop:disable Metrics/ClassLength
26
26
  class Tracer
27
27
  attr_reader \
28
28
  :trace_flush,
29
29
  :provider,
30
30
  :sampler,
31
+ :span_sampler,
31
32
  :tags
32
33
 
33
34
  attr_accessor \
@@ -56,6 +57,7 @@ module Datadog
56
57
  base_sampler: Sampling::AllSampler.new,
57
58
  post_sampler: Sampling::RuleSampler.new
58
59
  ),
60
+ span_sampler: Sampling::Span::Sampler.new,
59
61
  tags: {},
60
62
  writer: Writer.new
61
63
  )
@@ -64,6 +66,7 @@ module Datadog
64
66
  @enabled = enabled
65
67
  @provider = context_provider
66
68
  @sampler = sampler
69
+ @span_sampler = span_sampler
67
70
  @tags = tags
68
71
  @writer = writer
69
72
  end
@@ -323,7 +326,9 @@ module Datadog
323
326
  id: digest.trace_id,
324
327
  origin: digest.trace_origin,
325
328
  parent_span_id: digest.span_id,
326
- sampling_priority: digest.trace_sampling_priority
329
+ sampling_priority: digest.trace_sampling_priority,
330
+ # Distributed tags are just regular trace tags with special meaning to Datadog
331
+ tags: digest.trace_distributed_tags,
327
332
  )
328
333
  else
329
334
  TraceOperation.new(
@@ -341,7 +346,8 @@ module Datadog
341
346
  sample_trace(event_trace_op) if event_span_op && event_span_op.parent_id == 0
342
347
  end
343
348
 
344
- events.span_finished.subscribe do |_event_span, event_trace_op|
349
+ events.span_finished.subscribe do |event_span, event_trace_op|
350
+ sample_span(event_trace_op, event_span)
345
351
  flush_trace(event_trace_op)
346
352
  end
347
353
  end
@@ -461,20 +467,43 @@ module Datadog
461
467
  begin
462
468
  @sampler.sample!(trace_op)
463
469
  rescue StandardError => e
464
- Datadog.logger.debug { "Failed to sample trace: #{e}" }
470
+ SAMPLE_TRACE_LOG_ONLY_ONCE.run do
471
+ Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
472
+ end
465
473
  end
466
474
  end
467
475
 
476
+ SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
477
+ private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
478
+
479
+ def sample_span(trace_op, span)
480
+ begin
481
+ @span_sampler.sample!(trace_op, span)
482
+ rescue StandardError => e
483
+ SAMPLE_SPAN_LOG_ONLY_ONCE.run do
484
+ Datadog.logger.warn { "Failed to sample span: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
485
+ end
486
+ end
487
+ end
488
+
489
+ SAMPLE_SPAN_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
490
+ private_constant :SAMPLE_SPAN_LOG_ONLY_ONCE
491
+
468
492
  # Flush finished spans from the trace buffer, send them to writer.
469
493
  def flush_trace(trace_op)
470
494
  begin
471
495
  trace = @trace_flush.consume!(trace_op)
472
496
  write(trace) if trace && !trace.empty?
473
497
  rescue StandardError => e
474
- Datadog.logger.debug { "Failed to flush trace: #{e}" }
498
+ FLUSH_TRACE_LOG_ONLY_ONCE.run do
499
+ Datadog.logger.warn { "Failed to flush trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
500
+ end
475
501
  end
476
502
  end
477
503
 
504
+ FLUSH_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
505
+ private_constant :FLUSH_TRACE_LOG_ONLY_ONCE
506
+
478
507
  # Send the trace to the writer to enqueue the spans list in the agent
479
508
  # sending queue.
480
509
  def write(trace)
@@ -500,6 +529,5 @@ module Datadog
500
529
  end
501
530
  end
502
531
  end
503
- # rubocop:enable Metrics/ClassLength
504
532
  end
505
533
  end
@@ -175,6 +175,13 @@ module Datadog
175
175
  end
176
176
  end
177
177
  end
178
+
179
+ private
180
+
181
+ def reset_stats!
182
+ @traces_flushed = 0
183
+ @transport.stats.reset!
184
+ end
178
185
  end
179
186
  end
180
187
  end
@@ -48,6 +48,7 @@ module Datadog
48
48
  tag_runtime_id!
49
49
  tag_rate_limiter_rate!
50
50
  tag_sample_rate!
51
+ tag_sampling_decision_maker!
51
52
  tag_sampling_priority!
52
53
 
53
54
  trace
@@ -155,6 +156,12 @@ module Datadog
155
156
  )
156
157
  end
157
158
 
159
+ def tag_sampling_decision_maker!
160
+ return unless (decision = trace.sampling_decision_maker)
161
+
162
+ root_span.set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, decision)
163
+ end
164
+
158
165
  def tag_sampling_priority!
159
166
  return unless trace.sampling_priority
160
167
 
@@ -80,7 +80,7 @@ module Datadog
80
80
 
81
81
  if encoded.size > max_size
82
82
  # This single trace is too large, we can't flush it
83
- Datadog.logger.debug { "Dropping trace. Payload too large: '#{trace.map(&:to_hash)}'" }
83
+ Datadog.logger.debug { "Dropping trace. Payload too large: '#{trace.inspect}'" }
84
84
  Datadog.health_metrics.transport_trace_too_large(1)
85
85
 
86
86
  return nil
@@ -101,6 +101,8 @@ module Datadog
101
101
  # Make the trace serializable
102
102
  serializable_trace = SerializableTrace.new(trace)
103
103
 
104
+ Datadog.logger.debug { "Flushing trace: #{JSON.dump(serializable_trace)}" }
105
+
104
106
  # Encode the trace
105
107
  encoder.encode(serializable_trace)
106
108
  end
@@ -3,7 +3,7 @@
3
3
  module DDTrace
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 4
6
+ MINOR = 6
7
7
  PATCH = 1
8
8
  PRE = nil
9
9