ddtrace 1.4.2 → 1.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -2
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +0 -2
- data/lib/datadog/appsec/configuration/settings.rb +0 -2
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +0 -2
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/ci/ext/environment.rb +16 -4
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +0 -3
- data/lib/datadog/core/configuration/components.rb +8 -2
- data/lib/datadog/core/configuration/settings.rb +69 -2
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/header_collection.rb +41 -0
- data/lib/datadog/core/telemetry/collector.rb +0 -2
- data/lib/datadog/core/workers/async.rb +0 -2
- data/lib/datadog/profiling/collectors/old_stack.rb +1 -1
- data/lib/datadog/profiling.rb +1 -1
- data/lib/datadog/tracing/client_ip.rb +153 -0
- data/lib/datadog/tracing/configuration/ext.rb +12 -0
- data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +0 -2
- data/lib/datadog/tracing/contrib/ext.rb +19 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -2
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -4
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +92 -38
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +83 -9
- data/lib/datadog/tracing/flush.rb +57 -35
- data/lib/datadog/tracing/metadata/ext.rb +3 -9
- data/lib/datadog/tracing/metadata/tagging.rb +9 -0
- data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +10 -0
- data/lib/datadog/tracing/sampling/span/ext.rb +29 -0
- data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
- data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
- data/lib/datadog/tracing/sampling/span/sampler.rb +64 -0
- data/lib/datadog/tracing/span_operation.rb +0 -2
- data/lib/datadog/tracing/trace_operation.rb +22 -3
- data/lib/datadog/tracing/trace_segment.rb +1 -2
- data/lib/datadog/tracing/tracer.rb +31 -5
- data/lib/ddtrace/version.rb +2 -2
- metadata +19 -5
@@ -20,6 +20,16 @@ module Datadog
|
|
20
20
|
# * +sample_rate+: the sample rate as a {Float} between 0.0 and 1.0. 0.0
|
21
21
|
# means that no trace will be sampled; 1.0 means that all traces will be
|
22
22
|
# sampled.
|
23
|
+
#
|
24
|
+
# DEV-2.0: Allow for `sample_rate` zero (drop all) to be allowed. This eases
|
25
|
+
# DEV-2.0: usage for all internal users of the {RateSampler} class: both
|
26
|
+
# DEV-2.0: RuleSampler and Single Span Sampling leverage the RateSampler, but want
|
27
|
+
# DEV-2.0: `sample_rate` zero to mean "drop all". They work around this by hard-
|
28
|
+
# DEV-2.0: setting the `sample_rate` to zero like so:
|
29
|
+
# DEV-2.0: ```
|
30
|
+
# DEV-2.0: sampler = RateSampler.new
|
31
|
+
# DEV-2.0: sampler.sample_rate = sample_rate
|
32
|
+
# DEV-2.0: ```
|
23
33
|
def initialize(sample_rate = 1.0)
|
24
34
|
super()
|
25
35
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Tracing
|
5
|
+
module Sampling
|
6
|
+
module Span
|
7
|
+
# Single Span Sampling constants.
|
8
|
+
module Ext
|
9
|
+
# Accept all spans (100% retention).
|
10
|
+
DEFAULT_SAMPLE_RATE = 1.0
|
11
|
+
# Unlimited.
|
12
|
+
# @see Datadog::Tracing::Sampling::TokenBucket
|
13
|
+
DEFAULT_MAX_PER_SECOND = -1
|
14
|
+
|
15
|
+
# Sampling decision method used to come to the sampling decision for this span
|
16
|
+
TAG_MECHANISM = '_dd.span_sampling.mechanism'
|
17
|
+
# Sampling rate applied to this span, if a rule applies
|
18
|
+
TAG_RULE_RATE = '_dd.span_sampling.rule_rate'
|
19
|
+
# Rate limit configured for this span, if a rule applies
|
20
|
+
TAG_MAX_PER_SECOND = '_dd.span_sampling.max_per_second'
|
21
|
+
|
22
|
+
# This span was sampled on account of a Span Sampling Rule
|
23
|
+
# @see Datadog::Tracing::Sampling::Span::Rule
|
24
|
+
MECHANISM_SPAN_SAMPLING_RATE = 8
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -6,6 +6,8 @@ module Datadog
|
|
6
6
|
module Span
|
7
7
|
# Checks if a span conforms to a matching criteria.
|
8
8
|
class Matcher
|
9
|
+
attr_reader :name, :service
|
10
|
+
|
9
11
|
# Pattern that matches any string
|
10
12
|
MATCH_ALL_PATTERN = '*'
|
11
13
|
|
@@ -54,6 +56,13 @@ module Datadog
|
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
59
|
+
def ==(other)
|
60
|
+
return super unless other.is_a?(Matcher)
|
61
|
+
|
62
|
+
name == other.name &&
|
63
|
+
service == other.service
|
64
|
+
end
|
65
|
+
|
57
66
|
private
|
58
67
|
|
59
68
|
# @param pattern [String]
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ext'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Tracing
|
7
|
+
module Sampling
|
8
|
+
module Span
|
9
|
+
# Span sampling rule that applies a sampling rate if the span
|
10
|
+
# matches the provided {Matcher}.
|
11
|
+
# Additionally, a rate limiter is also applied.
|
12
|
+
#
|
13
|
+
# If a span does not conform to the matcher, no changes are made.
|
14
|
+
class Rule
|
15
|
+
attr_reader :matcher, :sample_rate, :rate_limit
|
16
|
+
|
17
|
+
# Creates a new span sampling rule.
|
18
|
+
#
|
19
|
+
# @param [Sampling::Span::Matcher] matcher whether this rule applies to a specific span
|
20
|
+
# @param [Float] sample_rate span sampling ratio, between 0.0 (0%) and 1.0 (100%).
|
21
|
+
# @param [Numeric] rate_limit maximum number of spans sampled per second. Negative numbers mean unlimited spans.
|
22
|
+
def initialize(
|
23
|
+
matcher,
|
24
|
+
sample_rate: Span::Ext::DEFAULT_SAMPLE_RATE,
|
25
|
+
rate_limit: Span::Ext::DEFAULT_MAX_PER_SECOND
|
26
|
+
)
|
27
|
+
|
28
|
+
@matcher = matcher
|
29
|
+
@sample_rate = sample_rate
|
30
|
+
@rate_limit = rate_limit
|
31
|
+
|
32
|
+
@sampler = Sampling::RateSampler.new
|
33
|
+
# Set the sample_rate outside of the initializer to allow for
|
34
|
+
# zero to be a "drop all".
|
35
|
+
# The RateSampler initializer enforces non-zero, falling back to 100% sampling
|
36
|
+
# if zero is provided.
|
37
|
+
@sampler.sample_rate = sample_rate
|
38
|
+
@rate_limiter = Sampling::TokenBucket.new(rate_limit)
|
39
|
+
end
|
40
|
+
|
41
|
+
# This method should only be invoked for spans that are part
|
42
|
+
# of a trace that has been dropped by trace-level sampling.
|
43
|
+
# Invoking it for other spans will cause incorrect sampling
|
44
|
+
# metrics to be reported by the Datadog App.
|
45
|
+
#
|
46
|
+
# Returns `true` if the provided span is sampled.
|
47
|
+
# If the span is dropped due to sampling rate or rate limiting,
|
48
|
+
# it returns `false`.
|
49
|
+
#
|
50
|
+
# Returns `nil` if the span did not meet the matching criteria by the
|
51
|
+
# provided matcher.
|
52
|
+
#
|
53
|
+
# This method modifies the `span` if it matches the provided matcher.
|
54
|
+
#
|
55
|
+
# @param [Datadog::Tracing::SpanOperation] span_op span to be sampled
|
56
|
+
# @return [:kept,:rejected] should this span be sampled?
|
57
|
+
# @return [:not_matched] span did not satisfy the matcher, no changes are made to the span
|
58
|
+
def sample!(span_op)
|
59
|
+
return :not_matched unless @matcher.match?(span_op)
|
60
|
+
|
61
|
+
if @sampler.sample?(span_op) && @rate_limiter.allow?(1)
|
62
|
+
span_op.set_metric(Span::Ext::TAG_MECHANISM, Span::Ext::MECHANISM_SPAN_SAMPLING_RATE)
|
63
|
+
span_op.set_metric(Span::Ext::TAG_RULE_RATE, @sample_rate)
|
64
|
+
span_op.set_metric(Span::Ext::TAG_MAX_PER_SECOND, @rate_limit)
|
65
|
+
:kept
|
66
|
+
else
|
67
|
+
:rejected
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def ==(other)
|
72
|
+
return super unless other.is_a?(Rule)
|
73
|
+
|
74
|
+
matcher == other.matcher &&
|
75
|
+
sample_rate == other.sample_rate &&
|
76
|
+
rate_limit == other.rate_limit
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -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,64 @@
|
|
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
|
+
# Return as soon as one rule matches
|
54
|
+
@rules.any? do |rule|
|
55
|
+
rule.sample!(span_op) != :not_matched
|
56
|
+
end
|
57
|
+
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
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
|
@@ -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,8 +112,22 @@ 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 ||
|
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!
|
@@ -233,6 +246,11 @@ module Datadog
|
|
233
246
|
end
|
234
247
|
end
|
235
248
|
|
249
|
+
# Returns a {TraceSegment} with all finished spans that can be flushed
|
250
|
+
# at invocation time. All other **finished** spans are discarded.
|
251
|
+
#
|
252
|
+
# @yield [spans] spans that will be returned as part of the trace segment returned
|
253
|
+
# @return [TraceSegment]
|
236
254
|
def flush!
|
237
255
|
finished = finished?
|
238
256
|
|
@@ -240,6 +258,8 @@ module Datadog
|
|
240
258
|
spans = @spans.dup
|
241
259
|
@spans = []
|
242
260
|
|
261
|
+
spans = yield(spans) if block_given?
|
262
|
+
|
243
263
|
# Use them to build a trace
|
244
264
|
build_trace(spans, !finished)
|
245
265
|
end
|
@@ -433,6 +453,5 @@ module Datadog
|
|
433
453
|
)
|
434
454
|
end
|
435
455
|
end
|
436
|
-
# rubocop:enable Metrics/ClassLength
|
437
456
|
end
|
438
457
|
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
|
@@ -36,6 +35,7 @@ module Datadog
|
|
36
35
|
|
37
36
|
# rubocop:disable Metrics/CyclomaticComplexity
|
38
37
|
# rubocop:disable Metrics/PerceivedComplexity
|
38
|
+
# @param spans [Array<Datadog::Span>]
|
39
39
|
def initialize(
|
40
40
|
spans,
|
41
41
|
agent_sample_rate: nil,
|
@@ -202,6 +202,5 @@ module Datadog
|
|
202
202
|
meta[TAG_SERVICE]
|
203
203
|
end
|
204
204
|
end
|
205
|
-
# rubocop:enable Metrics/ClassLength
|
206
205
|
end
|
207
206
|
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
|
@@ -341,7 +344,8 @@ module Datadog
|
|
341
344
|
sample_trace(event_trace_op) if event_span_op && event_span_op.parent_id == 0
|
342
345
|
end
|
343
346
|
|
344
|
-
events.span_finished.subscribe do |
|
347
|
+
events.span_finished.subscribe do |event_span, event_trace_op|
|
348
|
+
sample_span(event_trace_op, event_span)
|
345
349
|
flush_trace(event_trace_op)
|
346
350
|
end
|
347
351
|
end
|
@@ -461,20 +465,43 @@ module Datadog
|
|
461
465
|
begin
|
462
466
|
@sampler.sample!(trace_op)
|
463
467
|
rescue StandardError => e
|
464
|
-
|
468
|
+
SAMPLE_TRACE_LOG_ONLY_ONCE.run do
|
469
|
+
Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
470
|
+
end
|
465
471
|
end
|
466
472
|
end
|
467
473
|
|
474
|
+
SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
475
|
+
private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
|
476
|
+
|
477
|
+
def sample_span(trace_op, span)
|
478
|
+
begin
|
479
|
+
@span_sampler.sample!(trace_op, span)
|
480
|
+
rescue StandardError => e
|
481
|
+
SAMPLE_SPAN_LOG_ONLY_ONCE.run do
|
482
|
+
Datadog.logger.warn { "Failed to sample span: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
SAMPLE_SPAN_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
488
|
+
private_constant :SAMPLE_SPAN_LOG_ONLY_ONCE
|
489
|
+
|
468
490
|
# Flush finished spans from the trace buffer, send them to writer.
|
469
491
|
def flush_trace(trace_op)
|
470
492
|
begin
|
471
493
|
trace = @trace_flush.consume!(trace_op)
|
472
494
|
write(trace) if trace && !trace.empty?
|
473
495
|
rescue StandardError => e
|
474
|
-
|
496
|
+
FLUSH_TRACE_LOG_ONLY_ONCE.run do
|
497
|
+
Datadog.logger.warn { "Failed to flush trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
498
|
+
end
|
475
499
|
end
|
476
500
|
end
|
477
501
|
|
502
|
+
FLUSH_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
503
|
+
private_constant :FLUSH_TRACE_LOG_ONLY_ONCE
|
504
|
+
|
478
505
|
# Send the trace to the writer to enqueue the spans list in the agent
|
479
506
|
# sending queue.
|
480
507
|
def write(trace)
|
@@ -500,6 +527,5 @@ module Datadog
|
|
500
527
|
end
|
501
528
|
end
|
502
529
|
end
|
503
|
-
# rubocop:enable Metrics/ClassLength
|
504
530
|
end
|
505
531
|
end
|
data/lib/ddtrace/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -28,16 +28,22 @@ dependencies:
|
|
28
28
|
name: debase-ruby_core_source
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.10.16
|
34
|
+
- - "<="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.10.17
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- -
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: 0.10.16
|
44
|
+
- - "<="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.10.17
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: libddwaf
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -217,6 +223,7 @@ files:
|
|
217
223
|
- lib/datadog/core/error.rb
|
218
224
|
- lib/datadog/core/extensions.rb
|
219
225
|
- lib/datadog/core/git/ext.rb
|
226
|
+
- lib/datadog/core/header_collection.rb
|
220
227
|
- lib/datadog/core/logger.rb
|
221
228
|
- lib/datadog/core/logging/ext.rb
|
222
229
|
- lib/datadog/core/metrics/client.rb
|
@@ -339,6 +346,7 @@ files:
|
|
339
346
|
- lib/datadog/tracing.rb
|
340
347
|
- lib/datadog/tracing/analytics.rb
|
341
348
|
- lib/datadog/tracing/buffer.rb
|
349
|
+
- lib/datadog/tracing/client_ip.rb
|
342
350
|
- lib/datadog/tracing/configuration/ext.rb
|
343
351
|
- lib/datadog/tracing/context.rb
|
344
352
|
- lib/datadog/tracing/context_provider.rb
|
@@ -470,6 +478,7 @@ files:
|
|
470
478
|
- lib/datadog/tracing/contrib/excon/integration.rb
|
471
479
|
- lib/datadog/tracing/contrib/excon/middleware.rb
|
472
480
|
- lib/datadog/tracing/contrib/excon/patcher.rb
|
481
|
+
- lib/datadog/tracing/contrib/ext.rb
|
473
482
|
- lib/datadog/tracing/contrib/extensions.rb
|
474
483
|
- lib/datadog/tracing/contrib/faraday/configuration/settings.rb
|
475
484
|
- lib/datadog/tracing/contrib/faraday/connection.rb
|
@@ -582,6 +591,7 @@ files:
|
|
582
591
|
- lib/datadog/tracing/contrib/racecar/patcher.rb
|
583
592
|
- lib/datadog/tracing/contrib/rack/configuration/settings.rb
|
584
593
|
- lib/datadog/tracing/contrib/rack/ext.rb
|
594
|
+
- lib/datadog/tracing/contrib/rack/header_collection.rb
|
585
595
|
- lib/datadog/tracing/contrib/rack/integration.rb
|
586
596
|
- lib/datadog/tracing/contrib/rack/middlewares.rb
|
587
597
|
- lib/datadog/tracing/contrib/rack/patcher.rb
|
@@ -710,7 +720,11 @@ files:
|
|
710
720
|
- lib/datadog/tracing/sampling/rule.rb
|
711
721
|
- lib/datadog/tracing/sampling/rule_sampler.rb
|
712
722
|
- lib/datadog/tracing/sampling/sampler.rb
|
723
|
+
- lib/datadog/tracing/sampling/span/ext.rb
|
713
724
|
- lib/datadog/tracing/sampling/span/matcher.rb
|
725
|
+
- lib/datadog/tracing/sampling/span/rule.rb
|
726
|
+
- lib/datadog/tracing/sampling/span/rule_parser.rb
|
727
|
+
- lib/datadog/tracing/sampling/span/sampler.rb
|
714
728
|
- lib/datadog/tracing/span.rb
|
715
729
|
- lib/datadog/tracing/span_operation.rb
|
716
730
|
- lib/datadog/tracing/sync_writer.rb
|
@@ -778,7 +792,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
778
792
|
- !ruby/object:Gem::Version
|
779
793
|
version: 2.0.0
|
780
794
|
requirements: []
|
781
|
-
rubygems_version: 3.2.
|
795
|
+
rubygems_version: 3.2.26
|
782
796
|
signing_key:
|
783
797
|
specification_version: 4
|
784
798
|
summary: Datadog tracing code for your Ruby applications
|